Knowledge Partner Knowledge Partner
Knowledge Partner
717 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

An interesting task, Geoffrey...
I tried different things, but currently, I don't have a "working" solution.

In theory, we can have ECMA function with parameter nodeset, that can do this task.
Knowledge Partner Knowledge Partner
Knowledge Partner

I am pretty sure I could do this in ECMA. When you have a hammer, everything can look like a nail.

I have this urge to hit something with XPATH at the moment.

Micro Focus Expert
Micro Focus Expert

@geoffc, as I read the XPath string function definitions, they all require string arguments and not a node-set. It does not look like you will find something "clever" for this. Either looping or ECMA would seem to be your options. Possibly an XSLT stylesheet might be an option.

Cheers,

D

Knowledge Partner Knowledge Partner
Knowledge Partner

Usually when you pass a nodeset to a string function, it casts it as a string.  I think in the testing I was trying it would actually, concat all the strings into the nodset and tehn substring. So only the first value is shown since the rest were substringed away.

 

0 Likes
Vice Admiral
Vice Admiral

Thinking outside the box, if this is in a policy, set dummy operational attribute to those values and then reformat them? I have no idea if this would actually work, just something that popped to my mind.

Knowledge Partner Knowledge Partner
Knowledge Partner

Thank you, Sebastijan!
You right! In this specific case "thinking outside the box" and reformat operation attribute before copy value to Nodeset will work 🙂


Original doc (just for example):
<?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>
<instance class-name="User" src-dn="\TREE\org\user">
<association>xxx</association>
<attr attr-name="Internet EMail Address">
<value type="string">test1@test</value>
<value type="string">test2@test2.com.long-long-string</value>
</attr>
</instance>
</input>
</nds>

Policy:
<do-reformat-op-attr name="Internet EMail Address">
<arg-value type="string">
<token-substring length="17">
<token-local-variable name="current-value"/>
</token-substring>
</arg-value>
</do-reformat-op-attr>
<do-set-local-variable name="lvNS" scope="policy">
<arg-node-set>
<token-op-attr name="Internet EMail Address"/>
</arg-node-set>
</do-set-local-variable>
<do-set-local-variable name="lvClean" scope="policy">
<arg-node-set>
<token-xpath expression="$lvNS/text()"/>
</arg-node-set>
</do-set-local-variable>

Simulation:
NS2Substring :Applying policy: %+C%14CNS2String%-C.
NS2Substring : Applying to instance #1.
NS2Substring : Evaluating selection criteria for rule 'NS'.
NS2Substring : Rule selected.
NS2Substring : Applying rule 'NS'.
NS2Substring : Action: do-reformat-op-attr("Internet EMail Address",token-substring(length="17",token-local-variable("current-value"))).
NS2Substring : arg-string(token-substring(length="17",token-local-variable("current-value")))
NS2Substring : token-substring(length="17",token-local-variable("current-value"))
NS2Substring : token-substring(length="17",token-local-variable("current-value"))
NS2Substring : token-local-variable("current-value")
NS2Substring : Token Value: "test1@test".
NS2Substring : Arg Value: "test1@test".
NS2Substring : Token Value: "test1@test".
NS2Substring : Arg Value: "test1@test".
NS2Substring : arg-string(token-substring(length="17",token-local-variable("current-value")))
NS2Substring : token-substring(length="17",token-local-variable("current-value"))
NS2Substring : token-substring(length="17",token-local-variable("current-value"))
NS2Substring : token-local-variable("current-value")
NS2Substring : Token Value: "test2@test2.com.long-long-string".
NS2Substring : Arg Value: "test2@test2.com.long-long-string".
NS2Substring : Token Value: "test2@test2.com.l".
NS2Substring : Arg Value: "test2@test2.com.l".
NS2Substring : Action: do-set-local-variable("lvNS",scope="policy",arg-node-set(token-op-attr("Internet EMail Address"))).
NS2Substring : arg-node-set(token-op-attr("Internet EMail Address"))
NS2Substring : token-op-attr("Internet EMail Address")
NS2Substring : Token Value: {<value> @type = "string",<value> @type = "string"}.
NS2Substring : Arg Value: {<value> @type = "string",<value> @type = "string"}.
NS2Substring : Action: do-set-local-variable("lvClean",scope="policy",arg-node-set(token-xpath("$lvNS/text()"))).
NS2Substring : arg-node-set(token-xpath("$lvNS/text()"))
NS2Substring : token-xpath("$lvNS/text()")
NS2Substring : Token Value: {"test1@test","test2@test2.com.l"}.
NS2Substring : Arg Value: {"test1@test","test2@test2.com.l"}.
NS2Substring :Policy returned:
NS2Substring :
<nds dtdversion="4.0" ndsversion="8.x">
<source>
<product version="4.8.2.0">DirXML</product>
<contact>NetIQ Corporation</contact>
</source>
<input>
<instance class-name="User" src-dn="\TREE\org\user">
<association>xxx</association>
<attr attr-name="Internet EMail Address">
<value type="string">test1@test</value>
<value type="string">test2@test2.com.l</value>
</attr>
</instance>
</input>
</nds>

Knowledge Partner Knowledge Partner
Knowledge Partner

That is a clever idea.  The question is now one of performance. This is at the heart of a reasonably and slower than I want process, so I do not want to slow it down even more.

But this particular task is a rare one, so maybe not too bad... 

You actually took my thought, that I wanted to 'reformat op attr' inside a nodeset of values and made it into a stated idea that can work. Good one!

0 Likes
Commander
Commander

Depending on your use case, maybe you can use the join verb to convert it to a string, use regexp and then split it into a nodeset again? Something like this:

<do-set-local-variable name="yourSubstringedAttribute" scope="policy">
<arg-node-set>
<token-split delimiter="someUniqueString">
<token-replace-all regex="someUniqueString.{3}" replace-with="someUniqueString">
<token-join delimiter="someUniqueString">
<token-local-variable name="yourAttribute"/>
</token-join>
</token-replace-all>
</token-split>
</arg-node-set>
</do-set-local-variable>

Though it would only be able to substring at the beginning or end of the values, and it would break if any value is shorter than the length your're removing. I haven't tested this so there might be other issues.

Knowledge Partner Knowledge Partner
Knowledge Partner

Join is an interesting idea I had not considered. Can you explain your regex in there?

 

Replace SomeUniquestring.[3] with SomeUniquestring, ah I get it.

Join it with commas, (SomeUnqiueString variable) and then that string (a comma) followed by three characters.

Cute. Not sure that really handles my case well but a good idea!  Thanks!

0 Likes
Micro Focus Contributor
Micro Focus Contributor

If I would give that a try I would do a for-each, iterating the values get each of them and reformat, strip the current value and then use Append XML Text to insert the reformatted value.

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.

Best regards,
Tobias

Knowledge Partner Knowledge Partner
Knowledge Partner

That is an interesting idea as well, thank you.

I had already tested with for-each loop and copy to a new nodeset.  Using a counter to strip the positional and insert is also a good idea. 

Trying to think of which way is faster. 

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.