我一直在尝试使用XSLT将一些简单的XML转换为另一个简单的XML。我是XSLT的新手,所以如果有人能给我一个例子,我会扩展它。
我有任意XML文件:例如
<element>
<child_element>
<grandchild_element>
only one
</grandchild_element>
</child_element>
<child_element>
<grandchild_element>
one
</grandchild_element>
<grandchild_element>
two
</grandchild_element>
</child_element>
</element>
我想从中制作:
<tree>
<item class="element" id="1">
<item class="child_element" id="11">
<item class="grandchild_element" id="111" value="only one"/>
</item>
<item class="child_element" id="12">
<item class="grandchild_element" id="121" value="only one"/>
<item class="grandchild_element" id="122" value="only one"/>
</item>
</item>
</tree>
谢谢!
答案 0 :(得分:0)
您要为每个元素编写一个模板,例如:
<xsl:template match="child_element">
并使用前面或前面的兄弟元素的计数来获取“id”字段:
<xsl:template match="child_element">
<item>
<xsl:attribute name="id">
<xsl:value-of select="concat(count(preceding-sibling::element),count(preceding::child_element)+1)"/>
</xsl:attribute>
</item>
</xsl:template>
对于孙子女来说,你将不得不玩..和兄弟姐妹。 但是我强烈建议你不要将你当前的计数方案用于id:一旦你在任何级别有10个以上的节点,就会发生碰撞。
答案 1 :(得分:0)
要获得每个元素的 id ,您需要回顾每个祖先,并为每个级别计算前一个兄弟的数量。
<xsl:attribute name="id">
<xsl:apply-templates select="ancestor-or-self::*" mode="id"/>
</xsl:attribute>
<xsl:template match="*" mode="id">
<xsl:value-of select="count(preceding-sibling::*) + 1"/>
</xsl:template>
要将元素名称转换为类属性是直截了当的,请执行以下操作:
<xsl:attribute name="class">
<xsl:value-of select="local-name()"/>
</xsl:attribute>
将文本转换为值属性也非常简单。
<xsl:template match="text()">
<xsl:attribute name="value">
<xsl:value-of select="normalize-space(.)"/>
</xsl:attribute>
</xsl:template>
这里的 normalize-space 是删除示例XML中显示的换行符。
这是完整的XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Match root element -->
<xsl:template match="/">
<tree>
<xsl:apply-templates select="node()"/>
</tree>
</xsl:template>
<!-- Match any element in the XML -->
<xsl:template match="*">
<item>
<xsl:attribute name="id">
<xsl:apply-templates select="ancestor-or-self::*" mode="id"/>
</xsl:attribute>
<xsl:attribute name="class">
<xsl:value-of select="local-name()"/>
</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</item>
</xsl:template>
<!-- Used to match ancestors to work out the id -->
<xsl:template match="*" mode="id">
<xsl:value-of select="count(preceding-sibling::*) + 1"/>
</xsl:template>
<!-- Convert text into the value attribute -->
<xsl:template match="text()">
<xsl:attribute name="value">
<xsl:value-of select="normalize-space(.)"/>
</xsl:attribute>
</xsl:template>
<!-- Copy any existing attributes in the XML -->
<xsl:template match="@*">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML时,将输出以下内容:
<tree>
<item id="1" class="element">
<item id="11" class="child_element">
<item id="111" class="grandchild_element" value="only one"/>
</item>
<item id="12" class="child_element">
<item id="121" class="grandchild_element" value="one"/>
<item id="122" class="grandchild_element" value="two"/>
</item>
</item>
</tree>
答案 2 :(得分:0)
最简单/最短的解决方案之一(只有3个模板,没有模式,没有轴,没有count()
,只有一个xsl:attribute
)同时也是最通用的(与之配合使用)任何元素名称):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<tree>
<xsl:apply-templates/>
</tree>
</xsl:template>
<xsl:template match="*">
<xsl:variable name="vNumber">
<xsl:number count="*" level="multiple"/>
</xsl:variable>
<item class="{name()}"
id="{translate($vNumber, '.', '')}">
<xsl:apply-templates/>
</item>
</xsl:template>
<xsl:template match="text()">
<xsl:attribute name="value">
<xsl:value-of select="normalize-space()"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<element>
<child_element>
<grandchild_element>
only one
</grandchild_element>
</child_element>
<child_element>
<grandchild_element>
one
</grandchild_element>
<grandchild_element>
two
</grandchild_element>
</child_element>
</element>
产生了想要的正确结果:
<tree>
<item class="element" id="1">
<item class="child_element" id="11">
<item class="grandchild_element" id="111" value="only one"/>
</item>
<item class="child_element" id="12">
<item class="grandchild_element" id="121" value="one"/>
<item class="grandchild_element" id="122" value="two"/>
</item>
</item>
</tree>