Randy Bishop
Randy Bishop

Reputation: 35

xslt template only returns a single row

I have a xml file that is automatically created by another system that I need to pull data out of and join to another set of data. The nodes are recursive and I've tried using the template/apply template of the xsl transform but I always end up with only a single line rather than all the lines.

Here is a sample xml output:

<rdBookmarks>
  <Folders>
    <Folder Name="My Items" ID="">
      <Folder ID="a04593ac-41d5-44b4-a895-d4b6abe29984" Name="Student Summary" SaveTime="2014-10-21T11:08:41-04:00" />
      <Folder ID="4ef6e607-710d-4c52-abf7-de7377e33bd6" Name="Student Detail" SaveTime="2014-10-21T11:17:51-04:00" />
    </Folder>
  </Folders>
</rdBookmarks>

Here is my latest attempt at the xsl transform:

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
    <rdData>
        <xsl:apply-templates />
    </rdData>
</xsl:template>
<xsl:template match="Folder">
    <Folder>
        <xsl:attribute name="ID">
            <xsl:value-of select="Folder/@ID" />
        </xsl:attribute>
        <xsl:attribute name="Folder">
            <xsl:value-of select="Folder/@Name" />
        </xsl:attribute>
    </Folder>
</xsl:template>
</xsl:transform>

My current output is in the correct format, but it's only returning a single line and I can't figure out why.

<rdData>
    <Folder ID="a04593ac-41d5-44b4-a895-d4b6abe29984" Folder="Student Summary"/>
</rdData>

I found the answer at XSLT templates and recursion extremely helpful but it doesn't quite answer why I'm not getting multiple lines.

Upvotes: 0

Views: 1492

Answers (3)

Randy Bishop
Randy Bishop

Reputation: 35

Thanks to all who commented, your replies helped me find the solution. The reason I was only getting one of the sub folders rather than the main folder or both sub folders was because I was referencing the parent and calling the attributes of the child. I fixed the issue by removing the "Folder/" from the selects and adding in the "xsl:apply-templates" at the end. This goes through the parents and applies the same template to the children so that all folders are listed.

<xsl:template match="Folder">
    <Folder>
        <xsl:attribute name="ID">
            <xsl:value-of select="@ID" />
        </xsl:attribute>
        <xsl:attribute name="Folder">
            <xsl:value-of select="@Name" />
        </xsl:attribute>
    </Folder>
    <xsl:apply-templates />
</xsl:template>

Upvotes: 0

michael.hor257k
michael.hor257k

Reputation: 117083

I'm interested in all the folders, not just the two, so in my example it would ideally output 3 rows

Then I would suggest you try it this way:

XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
    <rdData>
        <xsl:apply-templates/>
    </rdData>
</xsl:template>

<xsl:template match="Folder">
    <Folder>
        <xsl:copy-of select="@ID | @Name"/>
   </Folder>
    <xsl:apply-templates/>
</xsl:template>

</xsl:transform>

Applied to your input example, the result is:

<?xml version="1.0" encoding="UTF-8"?>
<rdData>
   <Folder Name="My Items" ID=""/>
   <Folder ID="a04593ac-41d5-44b4-a895-d4b6abe29984" Name="Student Summary"/>
   <Folder ID="4ef6e607-710d-4c52-abf7-de7377e33bd6" Name="Student Detail"/>
</rdData>

Upvotes: 1

John Bollinger
John Bollinger

Reputation: 181034

Your template is producing just one row because that row is the result of transforming the outer <Folder> element (Folders/Folder) not the inner ones (Folders/Folder/Folder), and there is only one outer one.

Replacing your second template with the following should produce one <Folder> in the transformation for each inner <Folder> element, but I cannot be sure that the resulting stylesheet will transform all other inputs as you want.

<xsl:template match="Folder/Folder">
  <Folder>
    <xsl:attribute name="ID">
        <xsl:value-of select="@ID" />
    </xsl:attribute>
    <xsl:attribute name="Folder">
        <xsl:value-of select="@Name" />
    </xsl:attribute>
  </Folder>
</xsl:template>

Upvotes: 0

Related Questions