Some thoughts on XPATH in Novell Identity Manager

geoffc

By: geoffc

November 8, 2009 9:39 am

Reads: 472

Comments:0

Rating:0

The original iteration of Novell’s product started as DirXML 1 and (when it was still called Virtual Replicas, thus the engine’s name as a binary is still “vrdim” internal to the system.

In that build, all work was done in XSLT, the XML Style sheet Transformation language.

With the release of NSure Identity Manager 2.0 (gotta love the name changes) DirXML Script was introduced, which is an XML dialect that specifies conditions, actions, nouns, verbs, and tokens in a reasonably easy to read syntax that has an astonishing amount of power.

With each release of new versions of Identity Manager the functionality of DirXML Script gets better and better. Examples are things like the Unique Name (http://www.novell.com/communities/node/2209/unique-name-token-functionality-idm-35), Time, and Convert Time tokens (http://www.novell.com/communities/node/2572/using-time-tokens-idm-35). In both cases, you could do all the work in a rule you wrote yourself (for the case of Unique Name) or via a call to a Java class (Time and Convert Time). But the thing was, pretty much everybody needed to use one of these tokens in a project, so why not build a nice interface around it (Time and Convert Time’s interface versus the call to a Java class is such an improvement it is amazing to see! The Java time function is very very powerful, and the Time/Convert Time tokens expose most of it in a trivial to use fashion.).

XSLT is still here and supported in the latest versions of Novell Identity Manager, and in fact some drivers still use it by default, because what it does, is still not one hundred percent replicated by DirXML Script, or perhaps more correctly, XSLT is better suited to do the task. Examples are parts of the SAP HR/UAM drivers, where there is an external relationship between objects that is almost impossible (or so the original author told me in person, and that he had asked the worlds greatest expert on DirXML Script take on the task, before admitting it was currently impossible. If Father Ramon believed it could not be done in DirXML Script then it cannot be done) to do in DirXML Script.

The other example is the Delimited Text driver, which takes an incoming file CSV style file and performs a transform into an XDS formatted document. This is exactly the type of thing XSLT is designed for, and it truly shines in this space.

Having said that, most drivers use minimal XSLT these days as DirXML Script has become powerful enough to do almost everything needed.

If you cannot do it in DirXML Script, you have two more options, before falling back to XSLT. Call out to a custom Java class that you wrote to perform the specific task, or use XPATH. The scope of things you can do within your custom Java class is limited by your imagination and your access to API’s.

XPATH is the XML Path Language, and a good definition of the RFC is at this link:
http://www.w3.org/TR/1999/REC-xpath-19991116

What is nice about this link is that you can find functions that are supported by XPATH in an XPATH statement. It is worth mentioning that Novell Identity Manager only supports XPATH 1.0 and not XPATH 2.0. The issue of 2.0 support is a complex one, since apparently XPATH 2.0 is not backwards compatible with XPATH 1.0, and thus an upgrade of support to 2.0 could cause you to have to re-evaluate all the use of XPATH in your current drivers. Clearly this is NOT a customer friendly event to consider. I will be interested in seeing how Novell intends to handle this issue in the future, as it will no doubt become more pressing.

XPATH, like XSLT is relatively confusing, and reading the RFC is not always enlightening. There are a bunch of Identity Manager focused resources you can look at, the Support forums (forums.novell.com over HTTP or NNTP) to start with. There are lots of examples floating in previous message posts in that group. There are some Wiki sites with samples like:
http://wiki.novell.com/index.php/XPATH_Examples
http://ldapwiki.willeke.com/Wiki.jsp?page=IDMCodeSnippets

One issue that I find stalls many first timers as they encounter XPATH is the difference between selecting and evaluating.

XPATH is used in two very different contexts within an Identity Manager solution.

The most common use is to select a node in an XML document. The second usage is to call some function or do something with XPATH. Both approaches use the same language but are very different and confusing.

Selecting a node with an XML document (in the XDS dialect for Identity Manager) you can use the XPATH simulator in Designer pretty effectively.

Here is a sample of an add User document, and some of the things you can use XPATH to easily select.

<nds dtdversion="3.5" ndsversion="8.x">
  <source>
    <product version="3.5.10.20070918 ">DirXML</product>
    <contact>Novell, Inc.</contact>
  </source>
  <input>
    <modify class-name="User" dest-dn="\ACME-TREE\LAB\EMPLOYEES\ACTIVE\ljohnson" dest-entry-id="61535" event-id="ACMESMSLES10FS1#20080515175150#1#1" from-merge="true" qualified-src-dn="O=acme\OU=NYC\OU=FIN\CN=ljohnson" src-dn="acme\NYC\FIN\ljohnson" src-entry-id="34296">
      <association>{50BCE1E7-2D5F-dc01-80C5-330003000000}</association>
      <modify-attr attr-name="Password Expiration Time">
        <remove-all-values/>
      </modify-attr>
      <modify-attr attr-name="Login Time">
        <remove-all-values/>
      </modify-attr>
      <modify-attr attr-name="GUID">
        <remove-all-values/>
      </modify-attr>
      <modify-attr attr-name="NOVUser">
        <add-value>
          <value timestamp="1210875960#2" type="state">false</value>
        </add-value>
      </modify-attr>
      <modify-attr attr-name="Password Expiration Time">
        <add-value>
          <value timestamp="1210341755#17" type="time">1189381168</value>
        </add-value>
      </modify-attr>
      <modify-attr attr-name="GUID">
        <add-value>
          <value timestamp="1210341755#41" type="octet">gA8kk9Ad3RGIhwBQVrsTEw==</value>
        </add-value>
      </modify-attr>
    </modify>
  </input>
</nds>

It depends how you are using the XPATH to understand the context. For example, you might want to store a local variable with the DN of the source user. (Now this is not usually needed since there is a Source DN() token in Argument Builder, and an if-source-dn test in the Conditions section, but imagine you needed to do so.). You could set a local variable to the XPATH statement “@src-dn” which will select the value of src-dn in the modify node (acme\NYC\FIN\ljohnson). Lets say you called the variable SOURCE-DN.

You might have a condition with XPATH as the test. This can be XPATH is true or is not-true. Then you might want to say ‘if XPATH expression is true “@src-dn”‘ to test if there is a value for src-dn in the document. (As you may already know, not every document comes across with a src-dn or dest-dn set, and sometimes you need to be sure it is present before you try to use the value, with blind trust that it exists). This will return true if there is a value, and false if there is no value.

Those were a couple of examples of using selection. Now for an example of actions or functionality, lets say you might want to do a in-subtree test against a variable. In that case, you could use the XPATH function contains(). You really should for our example use the if-sourceDN condition in Policy Builder, and the in-subtree test, but for the purpose of our contrived example lets assume you want to do it the hard way. One realistic scenario would be when the object path you want to check is not the current object, but your retrieved the path somehow, say via a Distinguished Name syntax attribute, or maybe via a Query for the object. The Source DN and Destination DN condition tests only really apply to the object that is the focus of the current operational document.

First off it helps to know that variables can be used in XPATH by referencing them with a dollar sign ($) before the name.

You could then test if XPATH expression is true, contains($SOURCE-DN,”ACME\NY\FIN”) and expect either a true of false. If you wanted too you could use a Global Configuration Value as well, see this article http://www.novell.com/communities/node/4825/using-global-configuration-values-xpath for more details on that issue.

The easiest way I know of in Identity Manager to do math is in XPATH. I would set a local variable equal to an XPATH expression, and you can use variables and do basic math things. Like $TIME has the value of the current time in CTIME (Seconds since 1970) but I need 90 days from now. So I could set the local variable FUTURE-DATE to the XPATH of “$NOW + 90*24*60*60″. If I am not sure it is really an integer in my variable, I could use the function number() to convert it an integer.

I could have used a GCV to hold the value of 90 * 24 * 60 *60 or maybe a GCV (lets call it DaysInactive) for the 90 and multiply it by 86400 (seconds in a day, 24 * 60 * 60). Which would look more like XPATH of “$NOW + ~DaysInactive~*86400″.

String manipulation can be done in XPATH as well. While DirXML Script has a very powerful Replace All, Replace First, and Substring tokens, it does not do a good job of substring-before and substring-after, which XPATH supports.

Imagine you need to get the first part of a users email address, say the part before the @acme.com in ljohnson@acme.com. While you could use a Regular Expression to replace everything up to the @ symbol with nulls. Something like .+\@ will select everything up to @ symbol. But it is much easier to use the substring-after() XPATH function, so that my variable $EMAIL which holds the value ljohnson@acme.com, I could set the local variable $NAME equal to the XPATH statement of “substring-after($EMAIL,”@”) and you would end up with what you wanted.

There are a number of XPATH functions you can use, like concat(), starts-with(), substring-before(), substring-after(), substring(), string-length(), normalize-space(), and translate(). Check the XPATH reference at http://www.w3.org/TR/1999/REC-xpath-19991116 that I mentioned above for more XPATH possibilities.

Normalize-space() is one of my favorites and it is quite powerful and useful for cleaning up strings. It will replace any multiple occurrences of white space with a single space, and removing any leading and trailing spaces. Great if you do not trust the exact syntax of the string you are getting from your connected system. If you are doing string compares, the safest way to be sure they actually compare correctly when you want them too is to normalize-space both of them before you do the compare.

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

Tags: ,
Categories: Uncategorized

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.

Comment