I have a large number of xml files with a structure similar to the following, although they are far larger:
<?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>
I want to get the following output:
1|1|b1
1|2|b2
2|1|b1
2|2|b2
2|3|b3
where:
- Field 1 is the sequence number for nodes /a/b
- Field 2 is the sequence number of the attribute as it appears in the xml file
- Field 3 is the attribute name (not value)
I don't quite know how to calculate field 2 correctly.
I've prepared the following xslt file:
<?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>
but when I run the following command:
xsltproc a.xslt a.xml > a.csv
I get an incorrect output, as field 2 does not represent the attribute sequence number:
1|1|b1
1|1|b2
2|1|b1
2|1|b2
2|1|b3
Do you have any suggestions on how to get the correct output please?
Please notice that the answers provided in XSLT to order attributes do not provide a solution to this problem.
The order of attributes is irrelevant in XML. For instance, <a a1="3.0" a2="ABC">
and <a a1="3.0" a2="ABC">
are equivalent.
However this specific question is part of a larger application where it is essential to establish the order in which attributes appear in given xml files (and not in xml files that are equivalent to them).