XPATH Examples
This page is intent to help demystify XPATH expressions by showing example expressions with explanations as to what elements they match. Example traces are encouraged.
Contents
- 1 Reference Information
- 2 Examples
- 2.1 Strip Empty Values [Add]
- 2.2 Strip Empty Values [Modify]
- 2.3 Strip 'Remove All Values'
- 2.4 Component Value of a Structured Attribute (By Name)
- 2.5 Component Value of a Structured Attribute (By Position)
- 2.6 Detect a Warning Error
- 2.7 Detect a Merge Event
- 2.8 Retrieve a Portion of a String
- 2.9 Strip a Specific Value of a Specific Attribute
- 2.10 Remove Un-Associated Group Memberships
- 2.11 Query Vault for DN using Email address as a matching attribute
- 2.12 Run external code on the IDM engine server
- 2.13 Remove an attribute of an element
- 2.14 Get Value From a Nodeset
- 2.15 Allow Unsynchronized Values to Exist
Reference Information
XPATH 1.0 http://www.w3.org/TR/xpath
XPATH 2.0 http://www.w3.org/TR/xpath20
Note that xpath 2.0 is not supported by Novell Identity Manager as of Version 3.5
Geoff Carman's series on XPATH
http://www.novell.com/communities/node/4833/some-thoughts-xpath-novell-identity-manager
http://www.novell.com/communities/node/6175/xpath-and-context-node
http://www.novell.com/communities/node/6109/xpath-and-math
http://www.novell.com/communities/node/6179/using-string-compares-xpath-statements
http://www.novell.com/communities/node/6910/another-attempt-explaining-xpath-context-node
http://www.novell.com/communities/node/5845/using-xpath-examine-association-values
http://www.novell.com/communities/node/5686/cool-tricks-using-xpath-nodesets
http://www.novell.com/communities/node/4825/using-global-configuration-values-xpath
http://www.novell.com/communities/node/6276/using-xpath-get-position-node-node-set
http://www.novell.com/communities/node/5818/different-attribute-options-identity-manager
Examples
Strip Empty Values [Add]
This rule removes elements that have either an empty value [value="] or do not have a value defined [not(*)]
<rule> <description>Strip Empty Values [Add]</description> <conditions> <and> <if-operation mode="case" op="equal">add</if-operation> </and> </conditions> <actions> <do-strip-xpath expression="add-attr[value="]"/> <do-strip-xpath expression="add-attr[not(*)]"/> </actions> </rule>
When the above rule is applied to this input document:
<input> <add 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> <add-attr attr-name="cn"> <value>User1</value> </add-attr> <add-attr attr-name="Surname"> <value></value> </add-attr> <add-attr attr-name="Given Name"/> </add> </input>
The result is:
<input> <add 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> <add-attr attr-name="cn"> <value>User1</value> </add-attr> </add> </input>
The expression value=" matches the <value></value> and the expression not(*) matches the Given Name example above
Strip Empty Values [Modify]
This is similar to the above rule, but looks for elements that are modify values as opposed to add values.
<rule> <description>Strip Empty Values [Modify]</description> <conditions> <or> <if-operation mode="case" op="equal">modify</if-operation> <if-operation mode="case" op="equal">sync</if-operation> </or> </conditions> <actions> <do-strip-xpath expression="modify-attr/add-value[value=]"/> <do-strip-xpath expression="modify-attr[not(*)]"/> </actions> </rule>
Example Document that would have the value stripped:
<modify-attr attr-name="Surname"> <add-value> <value></value> </add-value> </modify-attr>
OR
<modify-attr attr-name="Surname"/>
Strip 'Remove All Values'
This removes the instance of <remove-all-values/> from an attribute named Surname
<do-strip-xpath expression="*[@attr-name='Surname']/remove-all-values"/>
If the above rule was applied to this document:
<modify-attr attr-name="Surname"> <remove-all-values/> <add-value> <value>Last Name1</value> </add-value> </modify-attr>
The result would be:
<modify-attr attr-name="Surname"> <add-value> <value>Last Name1</value> </add-value> </modify-attr>
Component Value of a Structured Attribute (By Name)
This rule will grab the value of a single component of a structured attribute using the component's name. This can be used with attributes like postal address.
<token-xpath expression="$current-node/component[@name='COMPONENT1']"/>
When applied to this example:
<modify-attr attr-name="Postal Address"> <remove-all-values/> <add-value> <value type="structured"> <component name="COMPONENT1">Address Name</component> <component name="COMPONENT2">1234 Street Address</component> <component name="COMPONENT3">Additional Street Address</component> <component name="COMPONENT4">City</component> <component name="COMPONENT5">State</component> <component name="COMPONENT6">84000</component> </value> </add-value> </modify-attr>
The value Address Name would be returned.
Component Value of a Structured Attribute (By Position)
This rule will grab the value of a single component of a structured attribute by it's position in the attribute. This can be used with attributes like postal address, where the components are not named.
<token-xpath expression="$current-node/component[2]"/>
When applied to this example:
<modify-attr attr-name="homePostalAddress"> <remove-all-values/> <add-value> <value> <component type="string">Herman Munster</component> <component type="string">1313 Mockingbird Lane</component> <component type="string">" "</component> <component type="string">Mockingbird Heights</component> <component type="string">MN</component> <component type="string">12345</component> </value> </add-value> </modify-attr>
The value "1313 Mockingbird Lane" will be returned.
Detect a Warning Error
This expression detects a warning returned on the driver.
<if-xpath op="true">self::status[@level = 'warning']</if-xpath>
For example:
<input> <status event-id="777" level="warning">Operation vetoed by unassociated object.</status> </input>
The subsequent rule:
<token-xpath expression="self::status"/>
Would return "Operation vetoed by unassociated object."
Detect a Merge Event
<conditions> <and> <if-operation op="equal">modify</if-operation> <if-xpath op="true">@from-merge = 'true'</if-xpath> </and> </conditions>
Retrieve a Portion of a String
This example grabs just the last portion of a string delimited by a hyphen
<actions> <do-set-local-variable name="vSSN" scope="policy"> <arg-node-set> <token-split delimiter="-"> <token-local-variable name="current-node"/> </token-split> </arg-node-set> </do-set-local-variable> <do-set-dest-attr-value name="vLAST4"> <arg-value> <token-xpath expression="$vSSN[3]"/> </arg-value> </do-set-dest-attr-value> </actions>
When applied to the value 333-22-4444 this would return just 4444
Strip a Specific Value of a Specific Attribute
<do-strip-xpath expression="*[@attr-name='CN']/add-value[value='Common Name']"/>
Removes this Value of Common Name:
<add-attr attr-name="cn"> <value>Common Name</value> </add-attr>
Which Returns:
<add-attr attr-name="cn"/>
You should then follow with the strip empty values rules above to clean this up.
Remove Un-Associated Group Memberships
You want to remove values of an attribute that do not contain a particular XML attribute
Input Document
<input> <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="Surname"> <remove-all-values/> <add-value> <value>Last Name1</value> </add-value> </modify-attr> <modify-attr attr-name="Given Name"> <remove-all-values/> <add-value> <value>First Name1</value> </add-value> </modify-attr> <modify-attr attr-name="Group Membership"> <add-value> <value association-ref="cn=groupname,o=myorg" type="dn">\Tree1\myorg\groupname</value> <value type="dn">\Tree1\myorg\anothergroup</value> <value association-ref="cn=yetonemore" type="dn">\Tree1\myorg\yetonemore</value> </add-value> </modify-attr> </modify> </input>
Policy
<rule> <description>Strip Unassociated Memberships</description> <conditions> <and> <if-op-attr name="Group Membership" op="available"/> </and> </conditions> <actions> <do-strip-xpath expression="*[@attr-name='Group Membership']/add-value/value[not(@association-ref)]"/> </actions> </rule>
Output Result
<input> <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="Surname"> <remove-all-values/> <add-value> <value>Last Name1</value> </add-value> </modify-attr> <modify-attr attr-name="Given Name"> <remove-all-values/> <add-value> <value>First Name1</value> </add-value> </modify-attr> <modify-attr attr-name="Group Membership"> <add-value> <value association-ref="cn=groupname,o=myorg" type="dn">\Tree1\myorg\groupname</value> <value association-ref="cn=yetonemore" type="dn">\Tree1\myorg\yetonemore</value> </add-value> </modify-attr> </modify> </input>
Query Vault for DN using Email address as a matching attribute
<rule> <description>Query Manager DN</description> <conditions> <and> <if-attr name="directSupervisorEmail" op="available"/> </and> </conditions> <actions> <do-set-local-variable name="DEST-DN" scope="policy"> <arg-string> <token-text xml:space="preserve">rackspace\users\active</token-text> </arg-string> </do-set-local-variable> <do-set-local-variable name="SEARCH-VALUE" scope="policy"> <arg-string> <token-attr name="directSupervisorEmail"/> </arg-string> </do-set-local-variable> <do-set-local-variable name="ManagerDN" scope="policy"> <arg-node-set> <token-xpath expression="query:search($destQueryProcessor, 'subtree',,$DEST-DN,,'Internet Email Address',$SEARCH-VALUE,)"/> </arg-node-set> </do-set-local-variable> <do-set-local-variable name="SRC-DN" scope="policy"> <arg-string> <token-xpath expression="$ManagerDN/@src-dn"/> </arg-string> </do-set-local-variable> </actions> </rule> <rule> <description>Display Direct Supervisor Query Result</description> <conditions> <and> <if-local-variable name="SRC-DN" op="available"/> </and> </conditions> <actions> <do-set-local-variable name="lvarManagerDN" scope="policy"> <arg-string> <token-parse-dn dest-dn-format="src-dn" start="0"> <token-local-variable name="SRC-DN"/> </token-parse-dn> </arg-string> </do-set-local-variable> <do-set-dest-attr-value name="manager"> <arg-value> <token-local-variable name="lvarManagerDN"/> </arg-value> </do-set-dest-attr-value> </actions> </rule>
Run external code on the IDM engine server
Windows only ;-)
<rule> <description>Start Notepad</description> <conditions/> <actions> <do-set-local-variable name="Runtime"> <arg-object> <token-xpath expression="java.lang.Runtime:getRuntime()"/> </arg-object> </do-set-local-variable> <do-set-local-variable name="Notepad"> <arg-object> <token-xpath expression="java.lang.Runtime:exec($Runtime, 'notepad.exe c:\NewDoc.txt')"/> </arg-object> </do-set-local-variable> <do-set-local-variable name="Returncode"> <arg-string> <token-xpath expression="java.lang.Process:waitFor($Notepad)"/> </arg-string> </do-set-local-variable> <do-set-local-variable name="Returncode"> <arg-string> <token-xpath expression="java.lang.Process:exitValue($Notepad)"/> </arg-string> </do-set-local-variable> </actions> </rule>
(with IDM versions earlier than 3.5 you need to define namespace for the java classes)
Remove an attribute of an element
From: Father Ramon \ Forums
This expression will strip an attribute of a value.
To remove the "type" attribute of the value below:
<attr attr-name="memberOf"> <value naming="true" type="dn">CN=dept,OU=groups,DC=domain,DC=com</value> </attr>
Apply this expression:
<do-strip-xpath expression="*[@attr-name="memberOf"]//value/@type"/>
Which would return this:
<attr attr-name="memberOf"> <value naming="true">CN=dept,OU=groups,DC=domain,DC=com</value> </attr>
This could also be accomplished without XPATH as below:
<do-reformat-op-attr name="memberOf"> <arg-value type="string"> <token-local-variable name="current-value"/> </arg-value> </do-reformat-op-attr>
From Father Ramon:
Reformat actually replaces all the existing values for the attributes with new ones. In that sense it is much more broad than the XPath approach because it actually throws away the original value elements and replaces it with a newly fabricated one that will only have on it exactly what you specify to put on it.
Get Value From a Nodeset
A query noun token returns its values in type nodeset. One way to get a specific value is to set a local variable using the query token and then use an xpath expression to return the desired value.
<token-xpath expression="$MyLocalVar//value[1]/text()"/>
Allow Unsynchronized Values to Exist
When an attribute is synchronized, you usually designate one system as authoritative. However, their could be instances where you want both to be authoritative. For example:
- Identity Vault Values
- Today
- Tomorrow
- Destination System Values
- Yesterday
<rule> <description>Merge Description Values</description> <comment xml:space="preserve">This rule will take any description values being sync'd and convert them to add value events instead of synchronization to preserve destination values.</comment> <conditions> <and> <if-op-attr name="Description" op="available"/> </and> </conditions> <actions> <do-set-local-variable name="lvDescription" scope="policy"> <arg-node-set> <token-op-attr name="Description"/> </arg-node-set> </do-set-local-variable> <do-set-local-variable name="lvDescriptionRemove" scope="policy"> <arg-node-set> <token-xpath expression="*[@attr-name='Description']/remove-value/value"/> </arg-node-set> </do-set-local-variable> <do-strip-op-attr name="Description"/> <do-for-each> <arg-node-set> <token-local-variable name="lvDescriptionRemove"/> </arg-node-set> <arg-actions> <do-remove-dest-attr-value name="Description"> <arg-value> <token-local-variable name="current-node"/> </arg-value> </do-remove-dest-attr-value> </arg-actions> </do-for-each> <do-for-each> <arg-node-set> <token-local-variable name="lvDescription"/> </arg-node-set> <arg-actions> <do-add-dest-attr-value name="Description"> <arg-value> <token-local-variable name="current-node"/> </arg-value> </do-add-dest-attr-value> </arg-actions> </do-for-each> </actions> </rule>
Resultant Values:
- Today
- Tomorrow
- Yesterday
Furthermore, removing a value that only exists in the vault, will simply remove that value in the destination.