问题
I have an xml as following:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE concept SYSTEM "aimlDomain.dtd">
<?xml-stylesheet type="text/xsl" href="aimlTest.xsl"?>
<concept>
<category>
<pattern>_ TOPIC ELEMENT ATTRIBUTE</pattern>
<template><srai>REQUIRED TOPIC AND MAP ELEMENT ATTRIBUTES</srai>
</template>
</category>
<category>
<pattern>TOPIC ELEMENT ATTRIBUTE _</pattern>
<template><srai>REQUIRED TOPIC AND MAP ELEMENT ATTRIBUTES</srai>
</template>
</category>
</concept>
The element category is the new domain I add with element specialization, which is specialized from foreign element.I want to transform the file into aiml, a new transformtype. The expected output shoud be like this:
` <?xml version="1.0" encoding="utf-8"?>
<category>
<pattern>_ TOPIC ELEMENT ATTRIBUTE</pattern>
<template><srai>REQUIRED TOPIC AND MAP ELEMENT ATTRIBUTES</srai>
</template>
</category>`
But there is nothing in the file except the declaratinon.The actual output is as following:
<?xml version="1.0" encoding="UTF-8"?>
Here is my aimlTest.xsl:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*[contains(@class, ' topic/topic topic/concept ')]">
<xsl:for-each select="*[contains(@class, ' topic/foreign category-d/category
')]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I want to know how to select the expected content.
回答1:
There are a lot of extraneous factors that are making this more complicated. One is matching on the @class attribute instead of element names. So I did a simplified version, see below.
Here is the input DITA file I used (I removed your DTD and XSLT PI because I didn't need them for this example):
<?xml version="1.0" encoding="utf-8"?>
<concept>
<category>
<pattern>_ TOPIC ELEMENT ATTRIBUTE</pattern>
<template>
<srai>REQUIRED TOPIC AND MAP ELEMENT ATTRIBUTES</srai>
</template>
</category>
<category>
<pattern>TOPIC ELEMENT ATTRIBUTE _</pattern>
<template>
<srai>REQUIRED TOPIC AND MAP ELEMENT ATTRIBUTES</srai>
</template>
</category>
</concept>
Here is the XSLT I used, matching only on element names:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="concept">
<root>
<xsl:for-each select="category">
<xsl:copy-of select="."/>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
I added a root element (called <root>
, could be any name) to the XSLT so the output would be proper XML.
And here is the output:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<category>
<pattern>_ TOPIC ELEMENT ATTRIBUTE</pattern>
<template>
<srai>REQUIRED TOPIC AND MAP ELEMENT ATTRIBUTES</srai>
</template>
</category>
<category>
<pattern>TOPIC ELEMENT ATTRIBUTE _</pattern>
<template>
<srai>REQUIRED TOPIC AND MAP ELEMENT ATTRIBUTES</srai>
</template>
</category>
</root>
If you want, you can refactor it back to use the @class attribute matching, but I suspect you don't need it. If you do need it, first make sure your DTD adds the class attributes properly. In the DITA DTDs, the class attributes are "defaulted", which means they are included in every XML instance, even if they are not literally in the XML (see the DITA DTDs for syntax). For publishing purposes, the DITA OT runs a preliminary process on the DITA XML files that pulls in all the defaulted @class attributes before the XSLT is run. Then the XML looks something like this:
<concept class=" topic/concept ">
<category class=" topic/foreign category-d/category ">
<pattern class=" etc ">_ TOPIC ELEMENT ATTRIBUTE</pattern>
<template class=" etc ">
<srai>REQUIRED TOPIC AND MAP ELEMENT ATTRIBUTES</srai>
</template>
</category>
[...]
And then your original XSLT could match on the class attributes. There's a good DITA reason for matching on these @class attributes but you might not need to do it, and you are adding complication by trying to do it.
来源:https://stackoverflow.com/questions/53717294/xslt-fails-to-transform-dita-into-new-type