このスタイルシートは作成ルールに使用できます。外部アプリケーションで作成されたエントリからeDirectoryユーザを作成する方法を示します。この例は、新しく採用された社員をまずHuman Resourcesデータベース内に作成し、その後ネットワーク上に作成するような場合です。ユーザの名前と姓を取り出し、eDirectoryツリーに固有のCNを生成します。eDirectoryでは、CNはコンテナ内で固有であれば良いことになっていますが、このスタイルシートは、eDirectoryツリーにあるすべてのコンテナでCNを固有にします。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- This stylesheet is an example of how to replace a create rule with an
XSLT stylesheet and that creates the User name from the Surname and
given Name attributes -->
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:query="http://www.novell.com/nxsl/java/com.novell.nds.dirxml.driver.
XdsQueryProcessor"
>
<!-- This is for testing the stylesheet outside of DirXML so things
are pretty to look at -->
<xsl:strip-space elements="*"/>
<xsl:preserve-space elements="value,component"/>
<xsl:output method="xml" indent="yes"/>
<!-- dirxml always passes two stylesheet parameters to an XSLT rule:
an inbound and outbound query processor -->
<xsl:param name="srcQueryProcessor"/>
<xsl:param name="destQueryProcessor"/>
<!-- match <add> elements -->
<xsl:template match="add">
<!-- ensure we have required NDS attributes we need for the name -->
<xsl:if test="add-attr[@attr-name='Surname'] and
add-attr[@attr-name='Given Name']">
<!-- copy the add through -->
<xsl:copy>
<!-- copy any attributes through except for the src-dn -->
<!-- we'll construct the src-dn below so that the placement rule will work -->
<xsl:apply-templates select="@*[string(.) != 'src-dn']"/>
<!-- call a template to construct the object name and place the result in a variable -->
<xsl:variable name="object-name">
<xsl:call-template name="create-object-name"/>
</xsl:variable>
<!-- now create the src-dn attribute with the created name -->
<xsl:attribute name="src-dn">
<xsl:variable name="prefix">
<xsl:call-template name="get-dn-prefix">
<xsl:with-param name="src-dn" select="string(@src-dn)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat($prefix,'\',$object-name)"/>
</xsl:attribute>
<!-- if we have a "CN" attribute, set it to the constructed name -->
<xsl:if test="./add-attr[@attr-name='CN']">
<add-attr attr-name="CN">
<value type="string"><xsl:value-of select="$object-name"/></value>
</add-attr>
</xsl:if>
<!-- copy the rest of the stuff through, except for what we have already copied -->
<xsl:apply-templates select="*[name() != 'add-attr' or @attr-name != 'CN'] |
comment() |
processing-instruction() |
text()"/>
<!-- add a <password> element -->
<xsl:call-template name="create-password"/>
</xsl:copy>
</xsl:if>
<!-- if the xsl:if fails, it means we don't have all the required attributes
so we won't copy the add through, and the create rule will veto the add -->
</xsl:template>
<!-- get-dn-prefix places the part of the passed dn that precedes the -->
<!-- last occurrance of '\' in the passed dn in a result tree fragment -->
<!-- meaning that it can be used to assign a variable value -->
<xsl:template name="get-dn-prefix" xmlns:jstring="http://www.novell.com/nxsl/java/java.lang.String">
<xsl:param name="src-dn"/>
<!-- use java string stuff to make this much easier -->
<xsl:variable name="dn" select="jstring:new($src-dn)"/>
<xsl:variable name="index" select="jstring:lastIndexOf($dn,'\')"/>
<xsl:if test="$index != -1">
<xsl:value-of select="jstring:substring($dn,0,$index)"/>
</xsl:if>
</xsl:template>
<!-- create-object-name creates a name for the user object and places the -->
<!-- result in a result tree fragment -->
<xsl:template name="create-object-name">
<!-- first try is first initial followed by surname -->
<xsl:variable name="given-name" select="add-attr[@attr-name='Given Name']/value"/>
<xsl:variable name="surname" select="add-attr[@attr-name='Surname']/value"/>
<xsl:variable name="prefix" select="substring($given-name,1,1)"/>
<xsl:variable name="object-name" select="concat($prefix,$surname)"/>
<!-- then see if name already exists in NDS -->
<xsl:variable name="exists">
<xsl:call-template name="query-object-name">
<xsl:with-param name="object-name" select="$object-name"/>
</xsl:call-template>
</xsl:variable>
<!-- if exists, then try 1st fallback, else return result -->
<xsl:choose>
<xsl:when test="$exists != ''">
<xsl:call-template name="create-object-name-2"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$object-name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- create-object-name-2 is the first fallback if the name created by -->
<!-- create-object-name already exists -->
<xsl:template name="create-object-name-2">
<!-- first try is first name followed by surname -->
<xsl:variable name="given-name" select="add-attr[@attr-name='Given Name']/value"/>
<xsl:variable name="surname" select="add-attr[@attr-name='Surname']/value"/>
<xsl:variable name="object-name" select="concat($given-name,$surname)"/>
<!-- then see if name already exists in NDS -->
<xsl:variable name="exists">
<xsl:call-template name="query-object-name">
<xsl:with-param name="object-name" select="$object-name"/>
</xsl:call-template>
</xsl:variable>
<!-- if exists, then try last fallback, else return result -->
<xsl:choose>
<xsl:when test="$exists != ''">
<xsl:call-template name="create-object-name-fallback"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$object-name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- create-object-name-fallback recursively tries a name created by -->
<!-- concatenating the surname and a count until NDS doesn't find -->
<!-- the name.There is a danger of infinite recursion, but only if -->
<!-- there is a bug in NDS -->
<xsl:template name="create-object-name-fallback">
<xsl:param name="count" select="1"/>
<!-- construct the a name based on the surname and a count -->
<xsl:variable name="surname" select="add-attr[@attr-name='Surname']/value"/>
<xsl:variable name="object-name" select="concat($surname,'-',$count)"/>
<!-- see if it exists in NDS -->
<xsl:variable name="exists">
<xsl:call-template name="query-object-name">
<xsl:with-param name="object-name" select="$object-name"/>
</xsl:call-template>
</xsl:variable>
<!-- if exists, then try again recursively, else return result -->
<xsl:choose>
<xsl:when test="$exists != ''">
<xsl:call-template name="create-object-name-fallback">
<xsl:with-param name="count" select="$count + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$object-name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- query object name queries NDS for the passed object-name.Ideally, this would -->
<!-- not depend on "CN":to do this, add another parameter that is the name of the -->
<!-- naming attribute.-->
<xsl:template name="query-object-name">
<xsl:param name="object-name"/>
<!-- build an xds query as a result tree fragment -->
<xsl:variable name="query">
<nds ndsversion="8.5" dtdversion="1.0">
<input>
<query>
<search-class class-name="{ancestor-or-self::add/@class-name}"/>
<!-- NOTE:depends on CN being the naming attribute -->
<search-attr attr-name="CN">
<value><xsl:value-of select="$object-name"/></value>
</search-attr>
<!-- put an empty read attribute in so that we don't get the whole object back -->
<read-attr/>
</query>
</input>
</nds>
</xsl:variable>
<!-- query NDS -->
<xsl:variable name="result" select="query:query($destQueryProcessor,$query)"/>
<!-- return an empty or non-empty result tree fragment depending on result of query -->
<xsl:value-of select="$result//instance"/>
</xsl:template>
<!-- create an initial password -->
<xsl:template name="create-password">
<password>
<xsl:value-of select="concat(add-attr[@attr-name='Surname']/value,'-',add-attr[@attr-name='CN']/value)"/>
</password>
</xsl:template>
<!-- identity transform for everything we don't want to mess with -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:transform>