Knowledge Partner Knowledge Partner
Knowledge Partner
808 views

How to substring all values in a nodeset?

I have a variable with a nodeset of values (imagine Set local variable to Source Attribute, that is multivalued.) and need to substring all the values...

Trying to think of the best way to do this...  I thought perhaps set local variable NODE to Xpath of substring($NODE,0,$LENGTH) but that returns nothing.

Of course I could for-each over it and copy it into a new nodeset.  But I want something more clever.

Hmm, could I clone by XPATH into a new one, with a substring in the clone?  Well first try did not work.

I feel like I am missing something obvious...

 

Labels (1)
0 Likes
16 Replies
Knowledge Partner Knowledge Partner
Knowledge Partner


@tljunggren wrote:

You will probably need a counter that keeps track of the current value node and use that in Strip By XPath Expression and Append XML Text.

No counter needed, just use $current-node:

<do-for-each>
<arg-node-set>
<token-local-variable name="nodeset"/>
</arg-node-set>
<arg-actions>
<do-set-local-variable name="substring" scope="policy">
<arg-string>
<token-xpath expression="substring-before($current-node,'@')"/>
</arg-string>
</do-set-local-variable>
<do-strip-xpath expression="$current-node/text()"/>
<do-append-xml-text expression="$current-node">
<arg-string>
<token-text xml:space="preserve">$substring$</token-text>
</arg-string>
</do-append-xml-text>
</arg-actions>
</do-for-each>

 

 

Test :    Applying rule 'Reformat Nodeset'.
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("trace",scope="policy",token-xml-serialize(notrace="true",token-local-variable("nodeset",notrace="true"))).
Test :        arg-string(token-xml-serialize(notrace="true",token-local-variable("nodeset",notrace="true")))
Test :          token-xml-serialize(notrace="true",token-local-variable("nodeset",notrace="true"))
Test :            -- trace suppressed --
Test :          Arg Value: "<value type="string">geoffc@cisny.com</value><value type="string">geoffrey@gmail.org</value>".
Test :      Action: do-for-each(arg-node-set(token-local-variable("nodeset"))).
Test :        arg-node-set(token-local-variable("nodeset"))
Test :          token-local-variable("nodeset")
Test :          Token Value: {<value> @type = "string",<value> @type = "string"}.
Test :          Arg Value: {<value> @type = "string",<value> @type = "string"}.
Test :        Performing actions for local-variable(current-node) = <value> @type = "string".
Test :          Action: do-set-local-variable("substring",scope="policy",token-xpath("substring-before($current-node,'@')")).
Test :            arg-string(token-xpath("substring-before($current-node,'@')"))
Test :              token-xpath("substring-before($current-node,'@')")
Test :                Token Value: "geoffc".
Test :              Arg Value: "geoffc".
Test :          Action: do-strip-xpath("$current-node/text()").
Test :          Action: do-append-xml-text("$current-node","$substring$").
Test :            arg-string("$substring$")
Test :              token-text("$substring$")
Test :                Expanded variable reference '$substring$' to 'geoffc'.
Test :              Arg Value: "geoffc".
Test :        Performing actions for local-variable(current-node) = <value> @type = "string".
Test :          Action: do-set-local-variable("substring",scope="policy",token-xpath("substring-before($current-node,'@')")).
Test :            arg-string(token-xpath("substring-before($current-node,'@')"))
Test :              token-xpath("substring-before($current-node,'@')")
Test :                Token Value: "geoffrey".
Test :              Arg Value: "geoffrey".
Test :          Action: do-strip-xpath("$current-node/text()").
Test :          Action: do-append-xml-text("$current-node","$substring$").
Test :            arg-string("$substring$")
Test :              token-text("$substring$")
Test :                Expanded variable reference '$substring$' to 'geoffrey'.
Test :              Arg Value: "geoffrey".
Test :      Action: do-set-local-variable("trace",scope="policy",token-xml-serialize(notrace="true",token-local-variable("nodeset",notrace="true"))).
Test :        arg-string(token-xml-serialize(notrace="true",token-local-variable("nodeset",notrace="true")))
Test :          token-xml-serialize(notrace="true",token-local-variable("nodeset",notrace="true"))
Test :            -- trace suppressed --
Test :          Arg Value: "<value type="string">geoffc</value><value type="string">geoffrey</value>".

 

 

 

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

That is more like what I was looking for. Still not quite the clever XPATH to do it all in one action, but I guess this one won't do it.

Thanks, that helps.

0 Likes
Knowledge Partner Knowledge Partner
Knowledge Partner

I actually use the above scheme a lot instead of token do-reformat-op-attr to preserve xml attrs on the value nodes that would otherwise be lost (here: value/@timestamp )

 

 

 

<?xml version="1.0" encoding="UTF-8"?><nds dtdversion="4.0" ndsversion="8.x">
	<source>
		<product version="4.8.2.0">DirXML</product>
		<contact>NetIQ Corporation</contact>
	</source>
	<input>
		<modify class-name="User" qualified-src-dn="o=dirXML Test\ou=Users\cn=User1" src-dn="o=dirXML Test\ou=Users\cn=User1">
			<association>o=dirXML Test\ou=Users\cn=User1</association>
			<modify-attr attr-name="Internet EMail Address">
				<remove-value>
					<value timestamp="20200101-9991231" type="string">geoffrey@gmail.org</value>
				</remove-value>
				<add-value>
					<value timestamp="20200101-9991231" type="string">geoffc@cisny.com</value>
				</add-value>
			</modify-attr>
		</modify>
	</input>
</nds>
Test :Applying policy: %+C%14Ctest%-C.
Test :  Applying to modify #1.
Test :    Evaluating selection criteria for rule 'Reformat Nodeset'.
Test :    Rule selected.
Test :    Applying rule 'Reformat Nodeset'.
Test :      Action: do-reformat-op-attr("Internet EMail Address",token-xpath("substring-before($current-value,'@')")).
Test :        arg-string(token-xpath("substring-before($current-value,'@')"))
Test :          token-xpath("substring-before($current-value,'@')")
Test :            Token Value: "geoffrey".
Test :          Arg Value: "geoffrey".
Test :        arg-string(token-xpath("substring-before($current-value,'@')"))
Test :          token-xpath("substring-before($current-value,'@')")
Test :            Token Value: "geoffc".
Test :          Arg Value: "geoffc".
Test :Policy returned:
Test :
<nds dtdversion="4.0" ndsversion="8.x">
  <source>
    <product version="4.8.2.0">DirXML</product>
    <contact>NetIQ Corporation</contact>
  </source>
  <input>
    <modify class-name="User" qualified-src-dn="o=dirXML Test\ou=Users\cn=User1" src-dn="o=dirXML Test\ou=Users\cn=User1">
      <association>o=dirXML Test\ou=Users\cn=User1</association>
      <modify-attr attr-name="Internet EMail Address">
        <remove-value>
          <value type="string">geoffrey</value>
        </remove-value>
        <add-value>
          <value type="string">geoffc</value>
        </add-value>
      </modify-attr>
    </modify>
  </input>
</nds>

 

 

 

 

 

 

 

Test :Applying policy: %+C%14Ctest%-C.
Test :  Applying to modify #1.
Test :    Evaluating selection criteria for rule 'Reformat Nodeset'.
Test :    Rule selected.
Test :    Applying rule 'Reformat Nodeset'.
Test :      Action: do-for-each(arg-node-set(token-removed-attr("Internet EMail Address")+token-op-attr("Internet EMail Address"))).
Test :        arg-node-set(token-removed-attr("Internet EMail Address")+token-op-attr("Internet EMail Address"))
Test :          token-removed-attr("Internet EMail Address")
Test :          Token Value: {<value> @timestamp = "20200101-9991231" @type = "string"}.
Test :          token-op-attr("Internet EMail Address")
Test :          Token Value: {<value> @timestamp = "20200101-9991231" @type = "string"}.
Test :          Arg Value: {<value> @timestamp = "20200101-9991231" @type = "string",<value> @timestamp = "20200101-9991231" @type = "string"}.
Test :        Performing actions for local-variable(current-node) = <value> @timestamp = "20200101-9991231" @type = "string".
Test :          Action: do-set-local-variable("substring",scope="policy",token-xpath("substring-before($current-node,'@')")).
Test :            arg-string(token-xpath("substring-before($current-node,'@')"))
Test :              token-xpath("substring-before($current-node,'@')")
Test :                Token Value: "geoffrey".
Test :              Arg Value: "geoffrey".
Test :          Action: do-strip-xpath("$current-node/text()").
Test :          Action: do-append-xml-text("$current-node","$substring$").
Test :            arg-string("$substring$")
Test :              token-text("$substring$")
Test :                Expanded variable reference '$substring$' to 'geoffrey'.
Test :              Arg Value: "geoffrey".
Test :        Performing actions for local-variable(current-node) = <value> @timestamp = "20200101-9991231" @type = "string".
Test :          Action: do-set-local-variable("substring",scope="policy",token-xpath("substring-before($current-node,'@')")).
Test :            arg-string(token-xpath("substring-before($current-node,'@')"))
Test :              token-xpath("substring-before($current-node,'@')")
Test :                Token Value: "geoffc".
Test :              Arg Value: "geoffc".
Test :          Action: do-strip-xpath("$current-node/text()").
Test :          Action: do-append-xml-text("$current-node","$substring$").
Test :            arg-string("$substring$")
Test :              token-text("$substring$")
Test :                Expanded variable reference '$substring$' to 'geoffc'.
Test :              Arg Value: "geoffc".
Test :Policy returned:
Test :
<nds dtdversion="4.0" ndsversion="8.x">
  <source>
    <product version="4.8.2.0">DirXML</product>
    <contact>NetIQ Corporation</contact>
  </source>
  <input>
    <modify class-name="User" qualified-src-dn="o=dirXML Test\ou=Users\cn=User1" src-dn="o=dirXML Test\ou=Users\cn=User1">
      <association>o=dirXML Test\ou=Users\cn=User1</association>
      <modify-attr attr-name="Internet EMail Address">
        <remove-value>
          <value timestamp="20200101-9991231" type="string">geoffrey</value>
        </remove-value>
        <add-value>
          <value timestamp="20200101-9991231" type="string">geoffc</value>
        </add-value>
      </modify-attr>
    </modify>
  </input>
</nds>

 

 

 

The fact that you can apply this to every kind of nodeset makes it very flexible and powerful. You can e.g. easily reformat several operation attributes at a time or only reformat the removed values or values matching a certain regex (or whatever selection you can make in xpath).

______________________________________________
https://www.is4it.de/identity-access-management
Micro Focus Contributor
Micro Focus Contributor

Depending on the situation you should store the values already (re)formatted in the IDVault.  If you really have to do the operation you describe I'd use XSLT since it concerns a node-set. The example stylesheet below consists of the default identity transformation template and a template for matching and reformatting the attribute 'mail' on a modify event. You'd have to adjust the stylesheet to match the event and attribute you want to reformat.

Example stylesheet:

<!-- identity transformation template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- reformat multivalued attrs -->
<xsl:template match="modify/modify-attr[@attr-name='mail']/add-value/value/text()">
<xsl:value-of select="substring(.,0,7)"/>
</xsl:template>
</xsl:stylesheet>

Sample Input XDS with modify event:

<modify class-name="User" qualified-src-dn="o=dirXML Test\ou=Users\cn=User1">
<association>o=dirXML Test\ou=Users\cn=User1</association>
<modify-attr attr-name="mail">
<remove-all-values/>
<add-value>
<value type="string">Last1@Name1</value>
<value type="string">Last2@Name1</value>
<value type="string">Last3@Name1</value>
</add-value>
</modify-attr>
</modify>
</input>

Sample Output XDS after stylesheet processing:

<modify class-name="User" qualified-src-dn="o=dirXML Test\ou=Users\cn=User1">
<association>o=dirXML Test\ou=Users\cn=User1</association>
<modify-attr attr-name="mail">
<remove-all-values/>
<add-value>
<value type="string">Last1@</value>
<value type="string">Last2@</value>
<value type="string">Last3@</value>
</add-value>
</modify-attr>
</modify>

Knowledge Partner Knowledge Partner
Knowledge Partner

I knew I could do it in a stylesheet. I need this in the middle of a policy buried deep in a loop. 

I made it work nicely, using simply the Split token.  I wanted initially to keep the <value> nodes, and split the one <value> node to many <value> nodes, but realized I could live with a simple nodeset of values so easy enough to do by changing the requirements.

0 Likes
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.