Reputation: 15
I have the following xml
<TopLevel>
<data m="R263">
<s ut="263firstrecord" lt="2013-02-16T09:21:40.393" />
<s ut="263secondrecord" lt="2013-02-16T09:21:40.393" />
</data>
<data m="R262">
<s ut="262firstrecord" lt="2013-02-16T09:21:40.393" />
<s ut="262secondrecord" lt="2013-02-16T09:21:40.393" />
</data>
</TopLevel>
I have some XSLT that does the call template but it's not itterating correctly.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="data">
<xsl:value-of select="@m" />
<xsl:variable name="vYourName" select="@m"/>
<xsl:choose>
<xsl:when test="@m='R262'">
<xsl:call-template name="R262"/>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="@m='R263'">
<xsl:call-template name="R263"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="R262">
<xsl:for-each select="/TopLevel/data/s">
Column1=<xsl:value-of select="@ut" />
Column2=<xsl:value-of select="@lt" />
</xsl:for-each>
</xsl:template>
<xsl:template name="R263">
<xsl:for-each select="/TopLevel/data/s">
Column1=<xsl:value-of select="@ut" />
Column2=<xsl:value-of select="@lt" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This gives me 8 records insead of the 4 (<s> level)
records. I know it has to do with my iteration ... but I am not sure how to address this.
I am also aware of the apply stylesheets but I couldn't unravel that mystery either ... If someone can help me with XSLT that will only process everything from <TopLevel>
to <\TopLevel>
checking the value of m at the <data>
level and applying the stylesheet at the <s>
level for each <s>
record I will be greateful beyond belief.
Upvotes: 0
Views: 729
Reputation: 1796
If you want to use match template
and apply-templates
you could do the following which gives you also a text output just like your stylesheet does. So this XSLT applied to your original source XML:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="data">
<xsl:value-of select="@m"/>
<xsl:apply-templates select="s"/>
</xsl:template>
<xsl:template match="s">
Column1=<xsl:value-of select="@ut"/>
Column2=<xsl:value-of select="@lt"/>
</xsl:template>
</xsl:stylesheet>
gives you this output:
<?xml version="1.0" encoding="UTF-8"?>
R263
Column1=263firstrecord
Column2=2013-02-16T09:21:40.393
Column1=263secondrecord
Column2=2013-02-16T09:21:40.393
R262
Column1=262firstrecord
Column2=2013-02-16T09:21:40.393
Column1=262secondrecord
Column2=2013-02-16T09:21:40.393
You basically only match on the s
and give out the attributes "ut" and "lt". You can also output XML which would look better.
Using this XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="data">
<list>
<xsl:apply-templates select="s"/>
</list>
</xsl:template>
<xsl:template match="s">
<xsl:element name="record">
<xsl:attribute name="m">
<xsl:value-of select="parent::data/@m"/>
</xsl:attribute>
<item>Column1=<xsl:value-of select="@ut"/></item>
<item>Column2=<xsl:value-of select="@lt"/></item>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
will give you this nice XML output:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<list>
<record m="R263">
<item>Column1=263firstrecord</item>
<item>Column2=2013-02-16T09:21:40.393</item>
</record>
<record m="R263">
<item>Column1=263secondrecord</item>
<item>Column2=2013-02-16T09:21:40.393</item>
</record>
</list>
<list>
<record m="R262">
<item>Column1=262firstrecord</item>
<item>Column2=2013-02-16T09:21:40.393</item>
</record>
<record m="R262">
<item>Column1=262secondrecord</item>
<item>Column2=2013-02-16T09:21:40.393</item>
</record>
</list>
You have to adapt the original XSLT a little bit to get a nice XML structure. Also when matching s
you "climb" up to element data
to get the R-numbers
for your attribute values.
The template matching root
you need for a proper XML root element. <list>
you could also get rid off then you have <record>
as child of <root>
.
Upvotes: 0
Reputation: 163595
I don't know what output you want to produce, but I suspect you want to replace
<xsl:for-each select="/TopLevel/data/s">
by
<xsl:for-each select="s">
that is, you only want to process the "s" elements within the "data" you are currently processing, rather than selecting all the "s" elements in the whole document.
Why not do this using apply-templates?
<xsl:template match="data">
...
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="s[../@m='R262']">
...
</xsl:template>
<xsl:template match="s[../@m='R263']">
...
</xsl:template>
Upvotes: 1