Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

position() not working?

Status
Not open for further replies.

glancep

Programmer
Aug 3, 2001
6
US
Alright... Here's what I'm trying to do.

<Doc>
<Head>
<Column>First Column</Column>
<Column>Second Column</Column>
<Column Numeric=&quot;true&quot;>Third Column</Column>
</Head>
<Body>
<Item>
<Field1>first</Field1>
<Field2>second</Field2>
<Field3>3</Field2>
</Item>
</Body>
</Doc>

I'm using XSLT to transform this XML into an HTML table... I'm trying to keep everything generic as possible (ie using XPath instead of specific node names) so that I can reuse the XSL.

What I need to do is recall the &quot;Numeric&quot; attribute from a for-each lower in the XML. I'm looping through each field in a given &quot;Item&quot; and if the &quot;Column&quot; node that corresponds with that field has 'true' for the Numeric attribute, then I want to right align that field in the table.

I'm having something like
<xsl:if test=&quot;/*/*[1]/*[position()]/@Numeric = true()&quot;> ...

Anyways, I'm not getting an error on the line or anything, it's just not coming up with the right thing. It's ALWAYS true.... so, to test it, I did a few xsl:value-of's to see what things were coming up as: the value-of /*/*[1]/*[position()] is ALWAYS the first item... even though the value-of position() is changing right, in that context, it's always 1. What am I doing wrong?

Thanks...
Gideon
 
if you do <xsl:value-of select=&quot;/*&quot;/> you will always end up with the first element in that part of the tree. this is because * will return a tree of elements but value-of selects just one element.

i think the [position()] in your XPath is redundant as this will always return true.

instead of using &quot;/*/*&quot; in your xpath you would be better off working from the current node &quot;./&quot;. i can't tell exactly what you are trying to do but i think you just need <xsl:if test=&quot;@Numeric = 'true'&quot;>

if you are still confused then post some more of the xsl code.
 
I'm sorry I was vague with the XML/XSL. I wanted to simplify the XML/XSL just to show specifically what was going on, but I got lazy.

Basically, here's the layout of my xml:
<document>
<header>
<title> ... title ... </title>
<columns>
<column> ... heading 1 ... </column>
<column> ... heading 2 ... </column>
<column numeric=&quot;true&quot;> ... heading 3 ... </column>
</columns>
</header>
<content>
<item>
<field> ... Item1 Data1 ... </field>
<field> ... Item1 Data2 ... </field>
<field> ... Item1 Data3 ... </field>
</item>
<item>
<field> ... Item2 Data1 ... </field>
<field> ... Item2 Data2 ... </field>
<field> ... Item2 Data3 ... </field>
</item>
<item>
<field> ... Item3 Data1 ... </field>
<field> ... Item3 Data2 ... </field>
<field> ... Item3 Data3 ... </field>
</item>
</content>
</document>

And I want it to transform into this:

title
heaing 1 heading 2 heading 3
-----------------------------------------------------
Item1 Data1 Item1 Data2 Item1 Data3 (right aligned)
Item2 Data1 Item2 Data2 Item2 Data3 (right aligned)
Item3 Data1 Item3 Data2 Item3 Data3 (right aligned)


So, basically I want to specify the column headings and the associated formatting at the top of the XML. So, in my XSL, when I'm for-each looping through each &quot;field&quot; in a given &quot;item,&quot; it needs to look back up at the top to the corresponding <column> node to see if the &quot;numeric=true&quot; is present. The key here is the CORRESPONDING column... so, if I'm at the node that says &quot;item3 data2&quot; then I want it to look for a &quot;numeric=true&quot; up in the &quot;column&quot; that says &quot;heading 2&quot; (since it's the second field in that item).

I can't navigate from the current node without backtracking to parent nodes, so I might as well express the path relative to the whole document. I'd end up with something like this:

/document/header/columns/column[2]/@Numeric

Right? Anyways, that makes sense to me. Now, I can't go hard-coding that &quot;2&quot; or it won't be generic for all the fields. So, I was wanting to use the &quot;position()&quot; function like so:

/document/header/columns/column[position()]/@Numeric

The problem is, in that context, position() always returns 1... not the position of the curront for-each loop. It's as though the path I'm specifying is overriding the context of the for-each.

------- Cur --------

Anyways, there's the explanation. Now, since I posted the original message, I have got a workaround. If I set a variable to the &quot;position()&quot; directly before trying to use it in the aforementioned path, it works perfectly. That would support my theory about the &quot;position()&quot; context being overridden by the specified path.

Out of curiosity (and for anyone else who may be working on the same issue), do you know if that is correct? And do you have any further comments about the issue?

Thanks
Gideon
 
ah, i see what you are doing now (i was probably reading your first post a bit too quickly). your workaround is the correct way to do this.

as a side note i always assumed that position() could also take a parameter but this doesn't seem to be the case. so your problem does seem to suggest that its implementation is not entirely useful since it is impossible to compare the positions of two nodes in 1 xpath query.

another xsl oddity to add to the list :)
 
I had that same problem once, and i think I fixed it the same way as you glancep.

Think of it this way, anything inside square brackets of an xpath syntax has baring on the axis of the node the brackets are attached to. By axis, I mean the criteria you are trying to select upon for the node you specifying as context. Therefore, whatever is inside square brackets will relate solely to the xpath node you are specifying, and not the context within which you are selecting.

The exceptions seem to be the relationship functions (current, parent self, etc), which even when within square brackets deal with the context of the node you are working with. AFAIK, any other functions (unless otherwise stated) will work solely on the current node you specify in the xpath expression you are building.

It is good to read the documentation for these functions to see what there effects will be, whether context or current nodes, and a good source for explanations is :)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top