我有大量的xml文件,其结构类似于以下内容,尽管它们要大得多:
<?xml version="1.0" encoding="UTF-8"?>
<a a1="3.0" a2="ABC">
<b b1="P1" b2="123">first
</b>
<b b1="P2" b2="456" b3="xyz">second
</b>
</a>
我想得到以下输出:
1|1|b1
1|2|b2
2|1|b1
2|2|b2
2|3|b3
其中:
我不太清楚如何正确计算字段2。
我已经准备了以下xslt文件:
<?xml version="1.0"?>
<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="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:for-each select="a/b/@*">
<xsl:value-of select="count(../preceding-sibling::*)+1"/>
<xsl:text>|</xsl:text>
<!-- TODO: This is not correct -->
<xsl:value-of select="count(preceding-sibling::*)+1"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
但是当我运行以下命令时:
xsltproc a.xslt a.xml > a.csv
我得到的输出不正确,因为字段2不代表属性序列号:
1|1|b1
1|1|b2
2|1|b1
2|1|b2
2|1|b3
关于如何获得正确的输出,您有任何建议吗?
请注意,XSLT to order attributes中提供的答案不能解决此问题。
在XML中,属性的顺序无关紧要。例如,<a a1="3.0" a2="ABC">
和<a a1="3.0" a2="ABC">
是等效的。
但是,这个特定问题是大型应用程序的一部分,在该应用程序中,必须确定属性在给定xml文件中的显示顺序(而不是在等效于它们的xml文件中)。
答案 0 :(得分:2)
尽管,正如kjhughes在评论中所述,属性顺序并不重要。但是,您仍然可以选择它们,并使用position()
元素来获取所需的数字(只是不能确定它们的输出顺序将是它们在XML中出现的顺序,尽管通常这样做是会是这种情况。)
尝试此XSLT。请注意xsl:for-each
的嵌套用法,以便在获取属性之前先仅选择b
个元素,以获取位置,然后再获取具有各自独立位置的属性。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:for-each select="a/b">
<xsl:variable name="bPosition" select="position()"/>
<xsl:for-each select="@*">
<xsl:value-of select="$bPosition"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="position()"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
您可以在要迭代的属性序列中使用项目的position()
,并结合逻辑来确定其父元素的位置。
<xsl:template match="/">
<xsl:for-each select="a/b/@*">
<xsl:value-of select="count(../preceding-sibling::*)+1"/>
<xsl:text>|</xsl:text>
<!-- TODO: This is not correct -->
<xsl:value-of select="position() -
(if (count(../preceding-sibling::*)) then count(../preceding-sibling::*)+1 else 0)"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
哪个会产生以下输出:
1|1|b1
1|2|b2
2|1|b1
2|2|b2
2|3|b3