Knowledge Partner Knowledge Partner
Knowledge Partner
156 views

XPATH Positions in Policy subtlety

I have noticed this before, and know how to fix it, but I was wondering what I am doing wrong here.

So in XPATH, $VAR is a nodeset with some values.

$VAR[2] should select the second node.

If $I=2, then $VAR[$I] should do the same thing.

But often I find that $VAR[$I] does not work, but that $VAR[position())=$I] does work.

Semantically [$I] and [position()=$I] should be the same... Yet they are often not...

I thought, maybe, $I is not coming across as a number, and maybe the test for position()= is a string compare?  But that seems odd.

I tested, by setting $I as XPATAH of number(1).  Then when I increment it in XPATH as number($I) + number(1) and same issue.

Then I tried in my $VAR[$I] doing it as $VAR[number($I)]

But $VAR[position()=$I] continues to work.  Anyone have an idea?

Labels (1)
2 Replies
Knowledge Partner Knowledge Partner
Knowledge Partner

I would guess your variable is a string in those cases where it does not work as expected, not a number. DirXMLScript has only three variable types: string, nodeset and object, no number type. So you'd have to make sure it's of object type with a number assigned in the moment you use it as a position descriptor. If you use a comparison like position()=$var then whatever $var is will be converted to a number using the number() function internally and you'll see the result you expected even if $var is string of digits.

 

Test :      Action: do-set-local-variable("nodeset",scope="policy",arg-node-set(token-src-attr("Internet EMail Address"))).
Test :        arg-node-set(token-src-attr("Internet EMail Address"))
Test :          token-src-attr("Internet EMail Address")
Test :            Query from policy
Test :            
<nds dtdversion="4.0" ndsversion="8.x">
  <source>
    <product version="4.8.2.0">DirXML</product>
    <contact>NetIQ Corporation</contact>
  </source>
  <input>
    <query class-name="User" dest-dn="o=dirXML Test\ou=Users\cn=User1" scope="entry">
      <read-attr attr-name="Internet EMail Address"/>
    </query>
  </input>
</nds>
Test :            Query from policy result
Test :            
<nds dtdversion="4.0" ndsversion="8.x">
  <source>
    <product version="4.8.2.0">DirXML</product>
    <contact>NetIQ Corporation</contact>
  </source>
  <output>
    <instance class-name="User">
      <attr attr-name="Internet EMail Address">
        <value type="string">geoffc@cisny.com</value>
        <value type="string">geoffrey@gmail.org</value>
      </attr>
    </instance>
  </output>
</nds>
Test :          Token Value: {<value> @type = "string",<value> @type = "string"}.
Test :          Arg Value: {<value> @type = "string",<value> @type = "string"}.
Test :      Action: do-set-local-variable("spos",scope="policy","2").
Test :        arg-string("2")
Test :          token-text("2")
Test :          Arg Value: "2".
Test :      Action: do-set-local-variable("npos",scope="policy",arg-object(token-xpath("number("2")"))).
Test :        arg-object(token-xpath("number("2")"))
Test :          token-xpath("number("2")")
Test :      Action: do-set-local-variable("mail",scope="policy",token-xpath("$nodeset[$spos]")).
Test :        arg-string(token-xpath("$nodeset[$spos]"))
Test :          token-xpath("$nodeset[$spos]")
Test :            Token Value: "geoffc@cisny.com".
Test :          Arg Value: "geoffc@cisny.com".
Test :      Action: do-set-local-variable("mail",scope="policy",token-xpath("$nodeset[position()=$spos]")).
Test :        arg-string(token-xpath("$nodeset[position()=$spos]"))
Test :          token-xpath("$nodeset[position()=$spos]")
Test :            Token Value: "geoffrey@gmail.org".
Test :          Arg Value: "geoffrey@gmail.org".
Test :      Action: do-set-local-variable("mail",scope="policy",token-xpath("$nodeset[$npos]")).
Test :        arg-string(token-xpath("$nodeset[$npos]"))
Test :          token-xpath("$nodeset[$npos]")
Test :            Token Value: "geoffrey@gmail.org".
Test :          Arg Value: "geoffrey@gmail.org".
Test :      Action: do-set-local-variable("mail",scope="policy",token-xpath("$nodeset[position()=$npos]")).
Test :        arg-string(token-xpath("$nodeset[position()=$npos]"))
Test :          token-xpath("$nodeset[position()=$npos]")
Test :            Token Value: "geoffrey@gmail.org".
Test :          Arg Value: "geoffrey@gmail.org".

 

 Comparisons in xpath have a few unintuitive touches, from https://www.w3.org/TR/1999/REC-xpath-19991116/#booleans:

When neither object to be compared is a node-set and the operator is = or !=, then the objects are compared by converting them to a common type as follows and then comparing them.

If at least one object to be compared is a boolean, then each object to be compared is converted to a boolean as if by applying the boolean function.

Otherwise, if at least one object to be compared is a number, then each object to be compared is converted to a number as if by applying the number function.

Otherwise, both objects to be compared are converted to strings as if by applying the string function.

______________________________________________
https://www.is4it.de/identity-access-management
Knowledge Partner Knowledge Partner
Knowledge Partner

I agree with your point.  But I have tried using number() on the value in multiple places trying to ensure that the string variable is distinctly a number. 

Still not working the way I want. Now this could be a Simulator issue since I happen to be working in it offline this morning. I wonder if maybe it is a Simulator'ism? 

But glad I am not missing anything very obvious.

 

The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.