By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,302 Members | 1,816 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,302 IT Pros & Developers. It's quick & easy.

directory structure xsl transformation question

P: n/a
I really have 2 questions regarding the following xml snippet. The xml is a
directory representation.

<?xml version="1.0" standalone="yes"?>
<FileSystem>
<Row>
<ID>1</ID>
<Name>Root</Name>
<Directory>Root</Directory>
<Dir>true</Dir>
<ParentID>0</ParentID>
</Row>
<Row>
<ID>2</ID>
<Name>c:\temp\boot\windowsapplication1\bin</Name>
<Directory>c:\temp\boot\windowsapplication1\bin</Directory>
<Dir>true</Dir>
<ParentID>0</ParentID>
<Row>
<ID>3</ID>
<Name>WindowsApplication1.exe</Name>
<Directory>c:\temp\boot\windowsapplication1\bin</Directory>
<Dir>false</Dir>
<BytesSize>17408</BytesSize>
<Extension>.exe</Extension>
<ParentID>2</ParentID>
</Row>
<Row>
<ID>4</ID>
<Name>WindowsApplication1.pdb</Name>
<Directory>c:\temp\boot\windowsapplication1\bin</Directory>
<Dir>false</Dir>
<BytesSize>19968</BytesSize>
<Extension>.pdb</Extension>
<ParentID>2</ParentID>
</Row>
</Row>
<Row>
<ID>5</ID>
<Name>c:\temp\boot\windowsapplication1\obj</Name>
<Directory>c:\temp\boot\windowsapplication1\obj</Directory>
<Dir>true</Dir>
<ParentID>0</ParentID>
<Row>
<ID>6</ID>
<Name>c:\temp\boot\windowsapplication1\obj\Debug </Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug</Directory>
<Dir>true</Dir>
<ParentID>5</ParentID>
<Row>
<ID>7</ID>
<Name>c:\temp\boot\windowsapplication1\obj\Debug\t emp</Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug\temp</Directory>
<Dir>true</Dir>
<ParentID>6</ParentID>
</Row>
<Row>
<ID>8</ID>
<Name>c:\temp\boot\windowsapplication1\obj\Debug\T empPE</Name>

<Directory>c:\temp\boot\windowsapplication1\obj\De bug\TempPE</Directory>
<Dir>true</Dir>
<ParentID>6</ParentID>
</Row>
<Row>
<ID>9</ID>
<Name>WindowsApplication1.exe</Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug</Directory>
<Dir>false</Dir>
<BytesSize>17408</BytesSize>
<Extension>.exe</Extension>
<ParentID>6</ParentID>
</Row>
<Row>
<ID>10</ID>
<Name>WindowsApplication1.Form1.resources</Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug</Directory>
<Dir>false</Dir>
<BytesSize>5925</BytesSize>
<Extension>.resources</Extension>
<ParentID>6</ParentID>
</Row>
<Row>
<ID>11</ID>
<Name>WindowsApplication1.pdb</Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug</Directory>
<Dir>false</Dir>
<BytesSize>19968</BytesSize>
<Extension>.pdb</Extension>
<ParentID>6</ParentID>
</Row>
</Row>
</Row>
1.) I would like the xslt to modify the structure so that the xml looks like
<folder>
<folder>
<file></file>
<file></file>
</folder>
</folder>

I need to change the row element name to either folder or file depending on
the variable Dir. I am using the following xslt but it would seem that there
is an easier way (or prettier way). I wasnt sure how to conditionaly change
the element name based on the variable. I tried a number of things bug it
would not run.

How can I improve the following xslt?

2.) Also, in the output xml the ParentID variable is always zero. Any
reason why?

thx
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>

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

<xsl:template match="Row">

<xsl:choose>
<xsl:when test="Dir='true'">
<xsl:call-template name="re">
<xsl:with-param name="kategoriat" select="."/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="re2">
<xsl:with-param name="kategoriat" select="."/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>

</xsl:template>

<xsl:template name="re">
<xsl:param name="kategoriat"/>
<xsl:choose>
<xsl:when test="$kategoriat">
<xsl:for-each select="$kategoriat">
<xsl:element name="Folder">
<xsl:attribute name="ID">
<xsl:value-of select="ID"/>
</xsl:attribute>
<xsl:attribute name="ParentID">
<xsl:value-of select="ParentID"/>
</xsl:attribute>
<xsl:attribute name="Text">
<xsl:value-of select="Name"/>
</xsl:attribute>
<xsl:attribute name="Dir">
<xsl:value-of select="Dir"/>
</xsl:attribute>

<xsl:choose>
<xsl:when test="./Row">

<xsl:choose>
<xsl:when test="Dir='true'">

<xsl:call-template name="re">
<xsl:with-param name="kategoriat" select="./Row"/>
</xsl:call-template>

</xsl:when>
<xsl:otherwise>

<xsl:call-template name="re2">
<xsl:with-param name="kategoriat" select="./Row"/>
</xsl:call-template>

</xsl:otherwise>

</xsl:choose>
</xsl:when>
</xsl:choose>

</xsl:element>

</xsl:for-each>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>

<xsl:template name="re2">
<xsl:param name="kategoriat"/>
<xsl:choose>
<xsl:when test="$kategoriat">
<xsl:for-each select="$kategoriat">
<xsl:element name="File">
<xsl:attribute name="ID">
<xsl:value-of select="ID"/>
</xsl:attribute>
<xsl:attribute name="ParentID">
<xsl:value-of select="ParentID"/>
</xsl:attribute>
<xsl:attribute name="Text">
<xsl:value-of select="Name"/>
</xsl:attribute>
<xsl:attribute name="Dir">
<xsl:value-of select="Dir"/>
</xsl:attribute>

<xsl:choose>
<xsl:when test="./Row">
<xsl:call-template name="re2">
<xsl:with-param name="kategoriat" select="./Row"/>
</xsl:call-template>
</xsl:when>

</xsl:choose>
</xsl:element>

</xsl:for-each>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

Dec 12 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a

"dave" <da**@discussions.microsoft.com> wrote in message
news:71**********************************@microsof t.com...
I really have 2 questions regarding the following xml snippet. The xml is a directory representation.

<?xml version="1.0" standalone="yes"?>
<FileSystem>
<Row>
<ID>1</ID>
<Name>Root</Name>
<Directory>Root</Directory>
<Dir>true</Dir>
<ParentID>0</ParentID>
</Row>
<Row>
<ID>2</ID>
<Name>c:\temp\boot\windowsapplication1\bin</Name>
<Directory>c:\temp\boot\windowsapplication1\bin</Directory>
<Dir>true</Dir>
<ParentID>0</ParentID>
<Row>
<ID>3</ID>
<Name>WindowsApplication1.exe</Name>
<Directory>c:\temp\boot\windowsapplication1\bin</Directory>
<Dir>false</Dir>
<BytesSize>17408</BytesSize>
<Extension>.exe</Extension>
<ParentID>2</ParentID>
</Row>
<Row>
<ID>4</ID>
<Name>WindowsApplication1.pdb</Name>
<Directory>c:\temp\boot\windowsapplication1\bin</Directory>
<Dir>false</Dir>
<BytesSize>19968</BytesSize>
<Extension>.pdb</Extension>
<ParentID>2</ParentID>
</Row>
</Row>
<Row>
<ID>5</ID>
<Name>c:\temp\boot\windowsapplication1\obj</Name>
<Directory>c:\temp\boot\windowsapplication1\obj</Directory>
<Dir>true</Dir>
<ParentID>0</ParentID>
<Row>
<ID>6</ID>
<Name>c:\temp\boot\windowsapplication1\obj\Debug </Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug</Directory>
<Dir>true</Dir>
<ParentID>5</ParentID>
<Row>
<ID>7</ID>
<Name>c:\temp\boot\windowsapplication1\obj\Debug\t emp</Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug\temp</Directory> <Dir>true</Dir>
<ParentID>6</ParentID>
</Row>
<Row>
<ID>8</ID>
<Name>c:\temp\boot\windowsapplication1\obj\Debug\T empPE</Name>

<Directory>c:\temp\boot\windowsapplication1\obj\De bug\TempPE</Directory>
<Dir>true</Dir>
<ParentID>6</ParentID>
</Row>
<Row>
<ID>9</ID>
<Name>WindowsApplication1.exe</Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug</Directory>
<Dir>false</Dir>
<BytesSize>17408</BytesSize>
<Extension>.exe</Extension>
<ParentID>6</ParentID>
</Row>
<Row>
<ID>10</ID>
<Name>WindowsApplication1.Form1.resources</Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug</Directory>
<Dir>false</Dir>
<BytesSize>5925</BytesSize>
<Extension>.resources</Extension>
<ParentID>6</ParentID>
</Row>
<Row>
<ID>11</ID>
<Name>WindowsApplication1.pdb</Name>
<Directory>c:\temp\boot\windowsapplication1\obj\De bug</Directory>
<Dir>false</Dir>
<BytesSize>19968</BytesSize>
<Extension>.pdb</Extension>
<ParentID>6</ParentID>
</Row>
</Row>
</Row>
1.) I would like the xslt to modify the structure so that the xml looks like <folder>
<folder>
<file></file>
<file></file>
</folder>
</folder>

I need to change the row element name to either folder or file depending on the variable Dir. I am using the following xslt but it would seem that there is an easier way (or prettier way). I wasnt sure how to conditionaly change the element name based on the variable. I tried a number of things bug it
would not run.

How can I improve the following xslt?

2.) Also, in the output xml the ParentID variable is always zero. Any
reason why?

thx
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>

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

<xsl:template match="Row">

<xsl:choose>
<xsl:when test="Dir='true'">
<xsl:call-template name="re">
<xsl:with-param name="kategoriat" select="."/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="re2">
<xsl:with-param name="kategoriat" select="."/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>

</xsl:template>

<xsl:template name="re">
<xsl:param name="kategoriat"/>
<xsl:choose>
<xsl:when test="$kategoriat">
<xsl:for-each select="$kategoriat">
<xsl:element name="Folder">
<xsl:attribute name="ID">
<xsl:value-of select="ID"/>
</xsl:attribute>
<xsl:attribute name="ParentID">
<xsl:value-of select="ParentID"/>
</xsl:attribute>
<xsl:attribute name="Text">
<xsl:value-of select="Name"/>
</xsl:attribute>
<xsl:attribute name="Dir">
<xsl:value-of select="Dir"/>
</xsl:attribute>

<xsl:choose>
<xsl:when test="./Row">

<xsl:choose>
<xsl:when test="Dir='true'">

<xsl:call-template name="re">
<xsl:with-param name="kategoriat" select="./Row"/>
</xsl:call-template>

</xsl:when>
<xsl:otherwise>

<xsl:call-template name="re2">
<xsl:with-param name="kategoriat" select="./Row"/>
</xsl:call-template>

</xsl:otherwise>

</xsl:choose>
</xsl:when>
</xsl:choose>

</xsl:element>

</xsl:for-each>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>

<xsl:template name="re2">
<xsl:param name="kategoriat"/>
<xsl:choose>
<xsl:when test="$kategoriat">
<xsl:for-each select="$kategoriat">
<xsl:element name="File">
<xsl:attribute name="ID">
<xsl:value-of select="ID"/>
</xsl:attribute>
<xsl:attribute name="ParentID">
<xsl:value-of select="ParentID"/>
</xsl:attribute>
<xsl:attribute name="Text">
<xsl:value-of select="Name"/>
</xsl:attribute>
<xsl:attribute name="Dir">
<xsl:value-of select="Dir"/>
</xsl:attribute>

<xsl:choose>
<xsl:when test="./Row">
<xsl:call-template name="re2">
<xsl:with-param name="kategoriat" select="./Row"/>
</xsl:call-template>
</xsl:when>

</xsl:choose>
</xsl:element>

</xsl:for-each>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

you can use recursion to do the needed:
The following xslt does the required transformation.

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml"/>

<xsl:template match="FileSystem">
<TREENODES>
<!-- processing row elements at top level-->
<xsl:for-each select="./Row[Dir='true']">
<xsl:call-template name="dirRow">
<xsl:with-param name="ID" select="ID"/>
</xsl:call-template>
</xsl:for-each>
</TREENODES>
</xsl:template>

<xsl:template name="dirRow">
<xsl:param name="ID"/>
<xsl:element name="folder">
<xsl:attribute name="name">
<xsl:value-of select="Name"/>
</xsl:attribute>
<xsl:attribute name="ID">
<xsl:value-of select="ID"/>
</xsl:attribute>
<xsl:attribute name="ParentID">
<xsl:value-of select="ParentID"/>
</xsl:attribute>
<!--call row template recursively for other row child elements-->
<!--notice the usage of ID element sent to this template as a parameter-->
<xsl:for-each select="./Row[Dir='true' and ParentID=$ID]">
<xsl:call-template name="dirRow">
<xsl:with-param name="ID" select="ID"/>
</xsl:call-template>
</xsl:for-each>
<!--call file template to process the files under this folder-->
<xsl:for-each select="./Row[Dir='false' and ParentID=$ID]">
<xsl:call-template name="fileRow">
</xsl:call-template>
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template name="fileRow">
<xsl:element name="file">
<xsl:attribute name="name">
<xsl:value-of select="Name"/>
</xsl:attribute>
<xsl:attribute name="ID">
<xsl:value-of select="ID"/>
</xsl:attribute>
<xsl:attribute name="ParentID">
<xsl:value-of select="ParentID"/>
</xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
hope this helps,
swapna


Dec 12 '05 #2

P: n/a
That is great. Thank you.

Do you know of any good resources to learn more about the recursive nature
of that xls?
thx
dave
Dec 13 '05 #3

P: n/a
This works good. I do have another question however.

When I open the xml file after the transformation it is all contained on 2
rows in the document. What is the easiest method have each row of the
transformed xml on a row by itself?

thanks
dave
Dec 15 '05 #4

P: n/a
dave wrote:
This works good. I do have another question however.

When I open the xml file after the transformation it is all contained
on 2
rows in the document. What is the easiest method have each row of the
transformed xml on a row by itself?


<xsl:output method="xml" indent="yes"/>

Depending on your processor, you may also need to specify a setting
for the strip-space action.

///Peter
--
XML FAQ: http://xml.silmaril.ie/

Dec 16 '05 #5

P: n/a
great...that worked super

I have modified the xsl above that formats the xml to folder/file structure
to now output html in a table, row format.

How do i incorporate the proper indentations in the html to represent the
existing directory file structure?

for example (this is what is desired)
folder
file
folder
file
file
folder
file
....
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:output method="xml" indent="yes"/>
<!-- variables -->
<xsl:variable name='TableStyle'>font-family:Verdana; font-size:67%;
text-align:left; vertical-align:top</xsl:variable>

<xsl:output method="xml"/>

<xsl:template match="FileSystem">
<html dir='ltr'>
<head>
<title>
FileSystem <xsl:value-of select="@LogonName"/>
</title>
</head>

<body style='margin:0'>
<table id='BodyTable' style="{$TableStyle}" cellspacing='0'>

<!-- processing row elements at top
level-->
<xsl:for-each select="./Row[Dir='true']">
<xsl:call-template name="dirRow">
<xsl:with-param name="ID"
select="ID"/>
</xsl:call-template>
</xsl:for-each>

</table>
</body>
</html>
</xsl:template>

<xsl:template name="dirRow">
<xsl:param name="ID"/>
<tr>
<td>
<xsl:value-of select="ID"/>
</td>
<td>
<xsl:value-of select="Name"/>
</td>
<td>
<xsl:value-of select="ParentID"/>
</td>
</tr>

<!--call row template recursively for other row child
elements-->
<!--notice the usage of ID element sent to this template as
a parameter-->
<xsl:for-each select="./Row[Dir='true' and ParentID=$ID]">
<xsl:call-template name="dirRow">
<xsl:with-param name="ID" select="ID"/>
</xsl:call-template>
</xsl:for-each>
<!--call file template to process the files under this
folder-->
<xsl:for-each select="./Row[Dir='false' and ParentID=$ID]">
<xsl:call-template name="fileRow">
</xsl:call-template>
</xsl:for-each>

</xsl:template>
<xsl:template name="fileRow">
<tr>
<td><xsl:value-of select="ID"/></td>
<td>
<xsl:value-of select="Name"/>
</td>
<td>
<xsl:value-of select="Extension"/>
</td>
<td>
<xsl:value-of select="BytesSize"/>
</td>
</tr>
</xsl:template>

</xsl:stylesheet>

Dec 16 '05 #6

P: n/a
dave wrote:
great...that worked super

I have modified the xsl above that formats the xml to folder/file
structure to now output html in a table, row format.

How do i incorporate the proper indentations in the html to represent
the existing directory file structure?


Use the same technique, <xsl:output method="html" indent="yes"/>

///Peter
--
XML FAQ: http://xml.silmaril.ie/

Dec 16 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.