strange xml xpath xsl error:

T

Tjerk Wolterink

I've xml code like this:

roles.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<roles xmlns="http://www.wolterinkwebdesign.com/xml/roles">

<!--
! The admin role.
! And admin should have all permisions to do its task
!
!-->
<role id="admin" isadmin="true">
<name>Administrator</name>
<description>De Administrator kan alles verwijderen, toevoegen en bewerken op de site.</description>
<grants>
<for name="all">
<action name="edit" grant="true" />
<action name="new" grant="true" />
<action name="read" grant="true" />
</for>
</grants>
</role>

<!--
! A generic visitor role.
! Anybody who is not given a role explicit is a visitor
!-->
<role id="visitor" isvisitor="true">
<name>Bezoeker</name>
<description>Bezoeker van de site</description>
a
<grants>
b
<for name="all">
<action name="read" grant="true" />
<action name="edit" grant="true" />
</for>
<for name="gastenboek">
<action name="new" grant="true"/>
<action name="edit" grant="true" />
</for>
<for name="medewerkers">
<action name="new" grant="true"/>
</for>
<for name="files">
y
<action name="new" grant="true">d</action>
</for>
<for name="news">
<action name="new" grant="true"/>
</for>
</grants>
</role>

</roles>


XSL code like this:
ps, $roles is always the above roles.xml


<!--
This template below works on for example
<page:button-edit-delete module="files" id="3"/>
-->
<xsl:template match="page:button-edit-delete">
<xsl:if test="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]/r:action[@name='edit']/@grant='true' or $roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='all']/r:action[@name='edit']/@grant='true'">
<[cut]
</xsl:if>
</xsl:template>

<!--
This template below does NOT work on for example
<page:button-new module="files" id="3"/>
-->
<xsl:template match="page:button-new">
<!-- debug code -->
BUTTON NEW MATCHED!
<xsl:value-of select="./@module"/>
<xsl:copy-of select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]"/>
<xsl:copy-of select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='files']"/>
<!-- end debug code -->

<xsl:if test="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]/r:action[@name='new']/@grant='true' or $roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='all']/r:action[@name='new']/@grant='true'">
[cut]
</xsl:if>
</xsl:template>


Strange enough:
this works: <xsl:value-of select="./@module"/> output:files
this does not work:
<xsl:copy-of select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]"/> output= ""
and this does work:
<xsl:copy-of select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='files']"/>

I do not understend the if test in the second template is almost the same as in the first template, but the first template always works and
the second not..... i cannot find the error
 
T

Tjerk Wolterink

[cut]

i've had the following solution:

<!--
! Matches a new button
!-->
<xsl:template match="page:button-new">
<xsl:variable name="module" select="./@module"/>
<xsl:if test="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=$module]/r:action[@name='new']/@grant='true' or $roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='all']/r:action[@name='new']/@grant='true'">
<div class="new_button">
<form enctype="multipart/form-data" action="$php_self" method="post">
<input type="hidden" name="module" value="{@module}" />
<input type="hidden" name="name" value="{@multiple}" />
<input type="hidden" name="new_request" value="true" />
<input class="new_button" type="submit" value="Nieuw item toevoegen" />
</form>
</div>
</xsl:if>
</xsl:template>



But that is ugly!! I think it must be possible without the xsl:variable
 
J

Joris Gillis

Strange enough:
this works: <xsl:value-of select="./@module"/> output:files
this does not work:
<xsl:copy-of select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]"/> output= ""
and this does work:
<xsl:copy-of select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='files']"/>

I do not understand the if test in the second template is almost the same as in the first template, but the first template always works and
the second not..... i cannot find the error

Hi,


you could use this:
<xsl:copy-of select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=current()/@module]"/>

Explanation:

In this Xpath expression:
<xsl:value-of select="./@module"/>
the period (.) selects the context node, which - in this case- is equal to the current node-set of the template.

But between the [brackets] in:
<xsl:copy-of select="/r:for[@name=./@module]"/>
, the context node is changed to the node preceding the left bracket ('r:for'). So this expression is trying to access the 'module' attribute of 'r:for'. In other words, you cannot access the current node-set with '.' when you're between brackets. You have to use 'current()' in stead.

regards,
 
T

Tjerk Wolterink

Joris said:
Strange enough:
this works: <xsl:value-of select="./@module"/> output:files
this does not work:
<xsl:copy-of
select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]"/>
output= ""
and this does work:
<xsl:copy-of
select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='files']"/>

I do not understand the if test in the second template is almost the
same as in the first template, but the first template always works and
the second not..... i cannot find the error

Hi,


you could use this:
<xsl:copy-of
select="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=current()/@module]"/>


Explanation:

In this Xpath expression:
<xsl:value-of select="./@module"/>
the period (.) selects the context node, which - in this case- is equal
to the current node-set of the template.

But between the [brackets] in:
<xsl:copy-of select="/r:for[@name=./@module]"/>
, the context node is changed to the node preceding the left bracket
('r:for'). So this expression is trying to access the 'module' attribute
of 'r:for'. In other words, you cannot access the current node-set with
'.' when you're between brackets. You have to use 'current()' in stead.

regards,

i thought of that, but i did not know current() existed.
But then how do you explain that this template works:

<xsl:template match="page:button-edit-delete">
<xsl:if test="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]/r:action[@name='edit']/@grant='true' or $roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='all']/r:action[@name='edit']/@grant='true'">
[cut]
</xsl:if>
</xsl:template>


And this one not:

<xsl:template match="page:button-new">
<xsl:if test="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]/r:action[@name='new']/@grant='true' or $roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='all']/r:action[@name='new']/@grant='true'">
[cut]
</xsl:if>
</xsl:template>


I do not understand that. the only differences ar in @name='edit' or @name='new' and in the match attribute of xsl:template.
Maybe i should give more detail?
 
J

Joris Gillis

i thought of that, but i did not know current() existed.
But then how do you explain that this template works:

<xsl:template match="page:button-edit-delete">
<xsl:if test="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]/r:action[@name='edit']/@grant='true' or $roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='all']/r:action[@name='edit']/@grant='true'">
[cut]
</xsl:if>
</xsl:template>


And this one not:

<xsl:template match="page:button-new">
<xsl:if test="$roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name=./@module]/r:action[@name='new']/@grant='true' or $roles/r:roles/r:role[@id=$role]/r:grants/r:for[@name='all']/r:action[@name='new']/@grant='true'" [cut]
</xsl:if>
</xsl:template>


I do not understand that. the only differences ar in @name='edit' or @name='new' and in the match attribute of xsl:template.
I'm not really sure either. One guess is that there's an 'action' node in your XML that does not have a 'name' attribute. That node would match the XPath expression because its non-existing 'name' attribute woulkd its non-existing 'module' attribute.

btw, I think it would be better to use a shorter notation like this:
<xsl:if test="//r:roles/r:role[@id=$role]/r:grants/r:for[@name='all' or @name=current()/@module]/r:action[@name='new']/@grant='true'">

regards,
 

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

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top