Reputation: 35
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
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
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
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