Recognising Sub-Items and sub-sub items using xslt

B

Ben

Hello! :)

im having a very annoying problem with XSLT

at the moment i have an xml with xslt, it displays the data as such:
C:\Test
- C:\Test\New Elf
- C:\Test\New Folder
C:\Te
- C:\Te\New Elf
- C:\Te\New Folder
C:\Te\New Elf
- C:\Te\New Elf\test2

the problem is the last element 'C:\Te\New Elf', it doesnt recognise
it's a sub element of C:\Te\, the current way i format the xml is

<UsersPermissions>
<userPermissions>
<user>WW00</user>
<rights>Read</rights>
<location>C:\Test</location>
</userPermissions>
<userPermissions>
<user>WW00</user>
<rights>Read</rights>
<location>C:\Test</location>
</userPermissions>
<userPermissions>
<user>WW0</user>
<rights>Read</rights>
<parent>C:\Test</parent>
<location>C:\Test\New Folder</location>
</userPermissions>
<userPermissions>
<user>WW0</user>
<rights>Read</rights>
<parent>C:\Test</parent>
<location>C:\Test\New Elf</location>
</userPermissions>
<userPermissions>
<user>WW00</user>
<rights>Read</rights>
<location>C:\Te</location>
</userPermissions>
<userPermissions>
<user>WW004\gb7senk1</user>
<rights>Read</rights>
<parent>C:\Te\New Elf</parent>
<location>C:\Te\New Elf\test2</location>
</userPermissions>

and the XSLT is formatted thusly

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="path" match="UsersPermissions/userPermissions"
use="parent"/>
<xsl:template match="/">
<html>
<head>
<script type="text/javascript" src="listCollapse.js"></script>
<style type="text/css">
ul.maketree, ul.maketree ul, ul.maketree li {
margin: 0;
padding: 0;
list-style-type: none;
}
ul.maketree ul { padding-left: 0.3em; }
ul.maketree li {
border-left: 1px dotted #000;
padding-left: 13px;
background: url(dotted.gif) scroll no-repeat 1px 0.8em;
}
ul.maketree li.last {
border-left-width: 0px;
padding-left: 14px;
background: url(dottedangle.gif) scroll no-repeat left top;
}

</style>

</head>
<body>
<script type="text/javascript">
window.onload = function () {
compactMenu('test1',false,'+ ');
selfLink('test1','selfhighlight',true);
}
</script>

<ul class="maketree" id="test1">
<xsl:for-each select="//userPermissions[generate-id(.)=
generate-id(key('path',parent)[1])]">
<li><xsl:if test="//userPermissions[location=current()/
parent]">
<xsl:value-of select="parent"/>
</xsl:if>
<ul>
<xsl:for-each select="//userPermissions[parent=current()/
parent]">
<xsl:sort select="location"/>
<li>
<xsl:value-of select="location"/>
</li>
</xsl:for-each>
</ul>
</li>
</xsl:for-each>
</ul>

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

</xsl:stylesheet>


Does anyone please know of a way to get thingy to understand the sub
elements are subelements?
if you compile the code you should see the problem

Thank you soo much in advance, this is driving me mad :)

Ben
 
G

George Bina

Hi Ben,

There are some inconsistencies in your XML file, the C:\Test is
defined twice and there is a missing definition for C:\Te\New Elf.
Now, assuming these are fixed and we have an input like below [1] then
one can assume the top parent folders are found if we look for
userPermissions elements without a parent child element. Then we
process recursively the identified locations putting in their content
and their children content, and so on, see the stylesheet below [2],
it produces the expected result.
Now, if you want to allow the inconsistencies that I mentioned in the
input files then you cannot use anymore the key as if you have a
missing folder you cannot link anymore from a parent to its content
and you need a different solution.

[1]

<UsersPermissions>
<userPermissions>
<user>WW00</user>
<rights>Read</rights>
<location>C:\Test</location>
</userPermissions>
<userPermissions>
<user>WW0</user>
<rights>Read</rights>
<parent>C:\Test</parent>
<location>C:\Test\New Folder</location>
</userPermissions>
<userPermissions>
<user>WW0</user>
<rights>Read</rights>
<parent>C:\Test</parent>
<location>C:\Test\New Elf</location>
</userPermissions>
<userPermissions>
<user>WW00</user>
<rights>Read</rights>
<location>C:\Te</location>
</userPermissions>
<userPermissions>
<user>WW004\gb7senk1</user>
<rights>Read</rights>
<parent>C:\Te</parent>
<location>C:\Te\New Elf</location>
</userPermissions>
<userPermissions>
<user>WW004\gb7senk1</user>
<rights>Read</rights>
<parent>C:\Te\New Elf</parent>
<location>C:\Te\New Elf\test2</location>
</userPermissions>
</UsersPermissions>


[2]

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="path" match="UsersPermissions/userPermissions"
use="parent"/>
<xsl:template match="/">
<html>
<head>
<script type="text/javascript" src="listCollapse.js"></script>
<style type="text/css">
ul.maketree, ul.maketree ul, ul.maketree li {
margin: 0;
padding: 0;
list-style-type: none;
}

ul.maketree ul { padding-left: 0.3em; }
ul.maketree li {
border-left: 1px dotted #000;
padding-left: 13px;
background: url(dotted.gif) scroll no-repeat 1px 0.8em;
}

ul.maketree li.last {
border-left-width: 0px;
padding-left: 14px;
background: url(dottedangle.gif) scroll no-repeat left top;

}

</style>

</head>
<body>
<script type="text/javascript">
window.onload = function () {
compactMenu('test1',false,'+ ');
selfLink('test1','selfhighlight',true);
}

</script>

<ul class="maketree" id="test1">
<xsl:for-each select="//userPermissions[not(parent)]">
<li>
<xsl:value-of select="location"/>
<xsl:call-template name="showContent">
<xsl:with-param name="parent" select="location"/>
</xsl:call-template>
</li>
</xsl:for-each>
</ul>

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

<xsl:template name="showContent">
<xsl:param name="parent"/>
<xsl:variable name="content" select="key('path', $parent)"/>
<xsl:if test="$content">
<ul>
<xsl:for-each select="key('path', $parent)">
<xsl:sort select="location"/>
<li>
<xsl:value-of select="location"/>
<xsl:call-template name="showContent">
<xsl:with-param name="parent" select="location"/>
</xsl:call-template>
</li>
</xsl:for-each>
</ul></xsl:if>
</xsl:template>
</xsl:stylesheet>

Best Regards,
George
 
B

Ben

Hi Ben,

There are some inconsistencies in your XML file, the C:\Test is
defined twice and there is a missing definition for C:\Te\New Elf.
Now, assuming these are fixed and we have an input like below [1] then
one can assume the top parent folders are found if we look for
userPermissions elements without a parent child element. Then we
process recursively the identified locations putting in their content
and their children content, and so on, see the stylesheet below [2],
it produces the expected result.
Now, if you want to allow the inconsistencies that I mentioned in the
input files then you cannot use anymore the key as if you have a
missing folder you cannot link anymore from a parent to its content
and you need a different solution.

[1]

<UsersPermissions>
<userPermissions>
<user>WW00</user>
<rights>Read</rights>
<location>C:\Test</location>
</userPermissions>
<userPermissions>
<user>WW0</user>
<rights>Read</rights>
<parent>C:\Test</parent>
<location>C:\Test\New Folder</location>
</userPermissions>
<userPermissions>
<user>WW0</user>
<rights>Read</rights>
<parent>C:\Test</parent>
<location>C:\Test\New Elf</location>
</userPermissions>
<userPermissions>
<user>WW00</user>
<rights>Read</rights>
<location>C:\Te</location>
</userPermissions>
<userPermissions>
<user>WW004\gb7senk1</user>
<rights>Read</rights>
<parent>C:\Te</parent>
<location>C:\Te\New Elf</location>
</userPermissions>
<userPermissions>
<user>WW004\gb7senk1</user>
<rights>Read</rights>
<parent>C:\Te\New Elf</parent>
<location>C:\Te\New Elf\test2</location>
</userPermissions>
</UsersPermissions>

[2]

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="path" match="UsersPermissions/userPermissions"
use="parent"/>
<xsl:template match="/">
<html>
<head>
<script type="text/javascript" src="listCollapse.js"></script>
<style type="text/css">
ul.maketree, ul.maketree ul, ul.maketree li {
margin: 0;
padding: 0;
list-style-type: none;
}

ul.maketree ul { padding-left: 0.3em; }
ul.maketree li {
border-left: 1px dotted #000;
padding-left: 13px;
background: url(dotted.gif) scroll no-repeat 1px 0.8em;
}

ul.maketree li.last {
border-left-width: 0px;
padding-left: 14px;
background: url(dottedangle.gif) scroll no-repeat left top;

}

</style>

</head>
<body>
<script type="text/javascript">
window.onload = function () {
compactMenu('test1',false,'+ ');
selfLink('test1','selfhighlight',true);
}

</script>

<ul class="maketree" id="test1">
<xsl:for-each select="//userPermissions[not(parent)]">
<li>
<xsl:value-of select="location"/>
<xsl:call-template name="showContent">
<xsl:with-param name="parent" select="location"/>
</xsl:call-template>
</li>
</xsl:for-each>
</ul>

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

<xsl:template name="showContent">
<xsl:param name="parent"/>
<xsl:variable name="content" select="key('path', $parent)"/>
<xsl:if test="$content">
<ul>
<xsl:for-each select="key('path', $parent)">
<xsl:sort select="location"/>
<li>
<xsl:value-of select="location"/>
<xsl:call-template name="showContent">
<xsl:with-param name="parent" select="location"/>
</xsl:call-template>
</li>
</xsl:for-each>
</ul></xsl:if>
</xsl:template>
</xsl:stylesheet>

Best Regards,
George

Ahh! thank you very much :D
i didnt understand how wrong i was with it, it works perfectly now,
thanks again :D

regards

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top