0

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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
user2263069
  • 15
  • 1
  • 3
  • Could you provide the expected result XML? This will help us see if your original XSLT could be revised to accomplish what you want. – ABach Apr 09 '13 at 19:03
  • I actually am just going to grab values out of each element and return them an insert statment ... I understand I can return them as a data set ... no idea yet ... that's the next question ... bottom line is for the above example I would be expecting to get 4 records 263firstrecord, 263secondrecord, 262firstrecord, 262secondrecord) with 2 columns each (column1 and column2). Thanks so much for responding I'm really outside my comfort zone with this xslt. – user2263069 Apr 09 '13 at 20:33
  • Hello, see my solution for a apply-templates logic. Regards, Peter – Peter Apr 10 '13 at 08:18

2 Answers2

1

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>
Michael Kay
  • 156,231
  • 11
  • 92
  • 164
0

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>.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Peter
  • 1,786
  • 4
  • 21
  • 40