Well that is a silly title, but I was having a conversation with some people I was helping and as always a major stumbling block for getting started with Identity Manager (IDM) is how XPATH works, which should be understandable, but in an Identity Manager context it seems to confuse the heck out of people.

This is actually fairly simple, once you understand a single concept: The default Current Context is the event node.

I have tried in most every XPATH article I write to focus on this issue since it is so important in the hopes that people looking for this kind of information will find one of the many attempts I have made in an attempt to tackle this major issue. They did update the docs a little bit to change this from a one line comment to a more useful example, but I wish they went further still.

As a quick reference, since I so enjoy quoting myself, but in useful ways, if you are new to IDM and find this article, you may be interested in reading my article series on things newcomers to IDM always need to learn: Common Mistakes IDM Newcomers Make Part 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 & 11. I figured this was an easy way to tackle some of the harder issues:

Then specific to XPATH, I would like to remind you of my other articles about XPATH:

Let me specifically call out the Examples Using XPATH article, as a great starting point if you need to get some info via XPATH and just cannot figure it out. If you come across a common example you think I should have included, please let me know so I can add it to that article for everyone’s benefit.

Anyway, I was helping out a newcomer to IDM who has given me so many ideas for articles (Thanks Amie!), and she gave me another great idea for this article. Since I no longer see some of these things as hard or obscure, they just seem natural, and thus the fresh perspective has been great for identifying topics I should talk about. We were working with Queries that returned a bunch of values. Lets say you want to find all objects in say a Work Order container that have a reference (lets say DirXML-nwoContent) to a workforceID. In other words you have been making Work Orders somewhere, to delay events, and one of the ways you identify the user who the Work Order applies to is by the workforceID stored in the DirXML-nwoContent attribute. She needed to get the values, and concatenate them together. But could not quite get the XPATH right to do the work.

Now if you read my Examples of using XPATH it will not directly help that much, since the use case is slightly different. This made me think of the various use cases for XPATH. I want to say contexts, but of course context means something else here. Hold onto this example, I will come back to it later. Basically, I can think of four types of cases that are common for using XPATH:

  1. To get something out of the current event.
  2. To get at data stored in a variable from a Source/Destination Attribute noun token.
  3. To get at data stored in a variable from the result of a Query noun token.
  4. Any other case

Ok that last one is silly, but lets deal with it first.

4. Any other case

It is possible that you might build an XML document into a variable, or perhaps receive it from an application (Say a SOAP driver, or maybe a database) and you know what it looks like, and you need to process it. Well that is completely unlimited in the possibilities, but simple in fact to explain what XPATH to use. I will assume that you get the data into a nodeset Local Variable somehow called XML-DATA. In that example, you would use the standard XPATH you can read about on W3 Schools and other sites that discuss XPATH.

You specify $XML-DATA/node/node[@XML-AttrName=”SomeValue”]/text() or whatever XPATH starting at your variable and walking the XML down to what you need. This is actually the simplest case, since this is exactly how XPATH is supposed to work, once you precede it with the $XML-DATA to tell it to look at it, starting at your variable level.

You can see lots of examples of how I did just this sort of thing in my series on how you might build a SOAP driver to talk to Salesforce.com: Getting Started Building a SOAP Driver for IDM – Part 1, 2, 3, 4, 5, 6, 7, 8 and 9

Now to start the rest in order.

1. To get something out of the current event.

This is the point I try to make in every article, and I will even repeat it in this one. The default current context that the IDM engine presents for XPATH is the event node. That is, when you see an event come into your driver, it might be an <add>, <modify>, <query>, or <instance> document. Lets use a simple <add> example first. This happens to be a Work Order being created.

<nds dtdversion=”4.0″ ndsversion=”8.x”>
  <source>
    <product edition=”Advanced” version=”4.0.1.0″>DirXML</product>
    <contact>Novell, Inc.</contact>
  </source>
  <input>
    <add cached-time=”20120213220429.429Z” class-name=”DirXML-WorkOrder” event-id=”server#20120213220429#2#2:c762f200-44ac-4026-84b1-00f262c7ac44″ qualified-src-dn=”O=services\OU=IDM\OU=WorkOrders\OU=Packing\CN=20120213170423-170100-1″ src-dn=”\ACME-DEV-03\services\IDM\WorkOrders\Packing\20120213170423-170100-1″ src-entry-id=”1977787″ timestamp=”1329170663#10″>
      <add-attr attr-name=”DirXML-nwoStatus”>
        <value timestamp=”1329170663#4″ type=”string”>pending</value>
      </add-attr>
      <add-attr attr-name=”DirXML-nwoContent”>
        <value timestamp=”1329170663#10″ type=”string”>\ACME-DEV-03\acme\users\JSmith</value>
      </add-attr>
      <add-attr attr-name=”DirXML-nwoSendToPublisher”>
        <value timestamp=”1329170663#5″ type=”state”>false</value>
      </add-attr>
      <add-attr attr-name=”DirXML-nwoDoItNowFlag”>
        <value timestamp=”1329170663#7″ type=”state”>false</value>
      </add-attr>
      <add-attr attr-name=”DirXML-DueDate”>
        <value timestamp=”1329170663#8″ type=”time”>1329170784</value>
      </add-attr>
      <add-attr attr-name=”DirXML-Other1″>
        <value timestamp=”1329170663#9″ type=”string”>JSmith</value>
      </add-attr>
      <add-attr attr-name=”DirXML-nwoDeleteDueDate”>
        <value timestamp=”1329170663#6″ type=”time”>1329192264</value>
      </add-attr>
    </add>
  </input>
</nds>

As discussed before, in a pure XPATH world, you would expect to need something like: nds/input/add/add-attr[@attr-name=’DirXML-Other1′]/value to get the JSmith value from the DirXML-Other1 in the document. But the engine cheats for you to make it easier. The current context, like the current directory in DOS is where you are starting and everything is relative to that starting point, and that assumes nds/input/add as the starting point. So to get the value of the DirXML-Other1 value all it takes is simply: add-attr[@attr-name=’DirXML-Other1′]/value

Maddening till you understand this, since the long way does not actually work! Yet every XPATH reference will tell you the short way does not work. 

Where this also matters a great deal is in the XPATH builder in Designer. Anytime you have an XPATH field, (if XPATH expression, XPATH noun in Argument Builder, or any of the Clone By XPATH, Strip By XPATH action tokens) there is a little icon that opens an XPATH builder window. Awesome you say, right? Copy in your XML document onto the left hand side, now you can build your XPATH in the right, and see that it works.

Well the trick here is that you need to select on the left hand side the Event node. That is the add, modify, etc. Since this is a generic XPATH tool, not IDM aware. So once you click in the right spot, then suddenly your XPATH examples will start to work. Drove me crazy for the longest time. Because I would have an XPATH I know works, but this tool would not show it working, until I clicked around randomly and suddenly it worked.

Some more quick examples. To get the src-dn so you know what the object DN is, is simply @src-dn which means the XML attribute (what the @ indicates you are selecting) of the current context node, which is the <add> node. More interesting is the @qualified-src-dn since you can then Parse DN that from Qualified Slash format to LDAP format if you need too.

2. To get at data stored in a variable from a Source/Destination Attribute noun token & 3. To get at data stored in a variable from the result of a Query noun token.

These two cases are really the same, they just require that you understand what the engine is doing for you.

A very common thing to do in IDM is to query for some object, store the result in a local variable, and then use XPATH upon the variable. Now it turns out there are two ways to do this (at least) and the results they return, and how you would XPATH them differ. The basic case, is the Query case, since that is the oldest. You set local variable QUERY (as a nodeset not a string) to the result of the query you want. 

<do-set-local-variable name=”QUERY” scope=”policy”>
    <arg-node-set>
        <token-query datastore=”src” scope=”entry”>
            <arg-dn>
                <token-text xml:space=”preserve”>o\ou\SomeUser</token-text>
            </arg-dn>
            <arg-string>
                <token-text xml:space=”preserve”>Given Name</token-text>
            </arg-string>
            <arg-string>
                <token-text xml:space=”preserve”>Surname</token-text>
            </arg-string>
        </token-query>
    </arg-node-set>
</do-set-local-variable>

This will generate a <query> event in the trace something like:

<nds dtdversion=”4.0″ ndsversion=”8.x”>
  <input>
    <query class-name=”umichRegistryObject” dest-dn=”o\ou\SomeUser” scope=”entry”>
      <read-attr attr-name=”Given Name”/>
      <read-attr attr-name=”Surame”/>
    </query>
  </input>
</nds>

Which will return a result something like:

<nds dtdversion=”4.0″ ndsversion=”8.x”>
  <source>
    <product edition=”Advanced” version=”4.0.1.0″>DirXML</product>
    <contact>Novell, Inc.</contact>
  </source>
  <output>
    <instance class-name=”User” event-id=”0″ qualified-src-dn=”O=O\OU=OU\CN=SomeUser” src-dn=”\ACME\O\OU\SomeUser” src-entry-id=”33120″>
      <attr attr-name=”Given Name”>
        <value timestamp=”1205335561#42″ type=”string”>Some Given Name</value>
      </attr>
      <attr attr-name=”Surname”>
        <value timestamp=”1205335561#42″ type=”string”>Some LastName</value>
      </attr>
    </instance>
  </output>
</nds>

Now you can perform XPATH upon the variable $QUERY as needed.

This is a silly example, since I know the DN of the target object since I specified it in my query, however, if I had searched instead, in my Query token, then the found object could be identified with an XPATH of:
$QUERY/@src-dn assuming there is only one response found. If there is more than one, that XPATH will likely get you a concatenated string of values. But you can check, using the XPATH of count($QUERY) which will return the number of <instance> nodes in the document.

However the thing to realize is that the current context is the <instance> node, actually just above it sort of. That is, if you were to for each over XPATH of $QUERY, then you would loop once, and the current-node would be the <instance> node. Thus inside a for each loop you could use the following example XPATH statements to get pieces out of it.

  • $current-node/@src-dn
  • $current-node/@qualified-src-dn
  • $current-node/attr[@attr-name=’Given Name’]/value

The other query case would be when you use the Source Attribute or Destination Attribute. If there is only going to be one value, then you can set it to a string local variable, and all you get is the string. This is because the XML nodeset is cast to a string and when you do that, you get the text() components as the result. However, in this case, the query you will see in the dstrace will be identical to the Query case, since after all it still needs to do the query to get the data, and the query syntax is the same, but the results will differ. In the Source attribute case, the context of your nodeset result be the <value> node, which might be one or many values.

Thus you CANNOT get the DN of the object, using $QUERY/@src-dn in this case, since the <instance> node is not included. Rather in our example above of the query for Surname, the nodeset, if you used the XML Serialize and Trace token to show the results would look more like:

<value timestamp=”1205335561#42″ type=”string”>Some LastName</value>

Thus you could do the following XPATH:

  • $QUERY/@timestamp
  • $QUERY/@type
  • $QUERY[2] (To get the second value, if more than one)

If you were loop over the nodeset, you would get one loop per value in the query result. Thus if you use a Query token vs a Source or Destination attribute token, to fill a nodeset local variable, the <query> event generated will look the same, but the results stored in the nodeset will differ. I found this one pretty confusing at first, and alas completely absent in the documentation.

What I would do to help visualize is to try the following code, which picks a user who must exist, by looking at Security Equals on the driver object, to get a DN, and then looks at a Query and Source Attribute of that user, and then traces them out.

<rule>
    <description>Visualize contents of nodeset variables</description>
    <comment name=”author” xml:space=”preserve”>Geoffrey Carman</comment>
    <comment name=”version” xml:space=”preserve”>1</comment>
    <comment name=”lastchanged” xml:space=”preserve”>Feb 20, 2012</comment>
    <conditions>
        <and/>
    </conditions>
    <actions>
        <do-set-local-variable name=”ADMIN” scope=”policy”>
            <arg-string>
                <token-src-attr name=”Security Equals”>
                    <arg-dn>
                        <token-global-variable name=”dirxml.auto.driverdn”/>
                    </arg-dn>
                </token-src-attr>
            </arg-string>
        </do-set-local-variable>
        <do-set-local-variable name=”QUERY” scope=”policy”>
            <arg-node-set>
                <token-query datastore=”src” scope=”entry”>
                    <arg-dn>
                        <token-local-variable name=”ADMIN”/>
                    </arg-dn>
                    <arg-string>
                        <token-text xml:space=”preserve”>*</token-text>
                    </arg-string>
                </token-query>
            </arg-node-set>
        </do-set-local-variable>
        <do-set-local-variable name=”SRC-ATTR” scope=”policy”>
            <arg-node-set>
                <token-src-attr name=”Surname”>
                    <arg-dn>
                        <token-local-variable name=”ADMIN”/>
                    </arg-dn>
                </token-src-attr>
            </arg-node-set>
        </do-set-local-variable>
        <do-trace-message level=”0″>
            <arg-string>
                <token-text xml:space=”preserve”>

Lets trace the results, first the Source Attribute of Surname, should just be a Value node:

</token-text>
                <token-xml-serialize>
                    <token-local-variable name=”SRC-ATTR”/>
                </token-xml-serialize>
                <token-text xml:space=”preserve”>

Then the longer results of the QUERY token for all the attrs of the object this driver is Security Equals to:

</token-text>
                <token-xml-serialize>
                    <token-local-variable name=”QUERY”/>
                </token-xml-serialize>
            </arg-string>
        </do-trace-message>
    </actions>
</rule>

I hope this helps, there is much to be confused about in XPATH, but hopefully this will clear up some of it.

1 vote, average: 5.00 out of 51 vote, average: 5.00 out of 51 vote, average: 5.00 out of 51 vote, average: 5.00 out of 51 vote, average: 5.00 out of 5 (1 votes, average: 5.00 out of 5)
You need to be a registered member to rate this post.
Loading...

Disclaimer: As with everything else at NetIQ Cool Solutions, this content is definitely not supported by NetIQ, so Customer Support will not be able to help you if it has any adverse effect on your environment.  It just worked for at least one person, and perhaps it will be useful for you too.  Be sure to test in a non-production environment.

Leave a Reply

No Comments
geoffc
By: geoffc
Aug 28, 2012
9:33 am
Reads:
6,353
Score:
5
Active Directory Authentication Automation Cloud Computing Cloud Security Configuration Customizing Data Breach DirXML Drivers End User Management Identity Manager Importing-Exporting / ICE/ LDIF Intelligent Workload Management IT Security Knowledge Depot LDAP Monitoring Open Enterprise Server Passwords Reporting Secure Access Supported Troubleshooting Workflow