1. | Generating same IDs across invocations |
| Jeni Tennison How to do this really depends on whether and in what way your source
document is going to change across invocations. A simple approach is to
generate an id that uniquely identifies the element within the document by
numbering all the elements of a certain type:
<xsl:attribute name="id">
<xsl:value-of select="name()">-<xsl:number level="any" />
</xsl:attribute>
will generate para-1, para-2, para-3 and so on throughout the document.
The xsl:number with level="any" numbers instances of the element across the
entire document. This is enough if your source document is not going to
change at all across invocations.
Otherwise you need something a bit more complex, and that relies on asking
the question: what is it that uniquely identifies this element? It could
be its content, the combination of values of attributes, its position, or
anything. Once you've answered that question, you can use the answer to
generate the unique id.
|
2. | ID attributes |
| Chris Maden Q expansion: I have an XML instance that makes use of the
ID/IDREF attributes to establish links within the document,
If I use "id($targetid)" it does not work.
For this to work, the ID attributes must be declared as
such, and the processor must read those declarations. If
you're using XT, for example, you need to have the
declarations in the DTD.
|
3. | Using keys instead of ID values |
| Joerg Pietschmann The id() function searches the whole
tree. But there must exist a DTD for this tree, which declares the
attribute ID as ID ( See http://www.xmlfiles.com/dtd/dtd_attributes.asp).
If you don't want to have a DTD, you can set up a key <xsl:key name="nodes" match="node" use="@ID"/>
as top-level.
And later in a template
<xsl:apply-templates select="key('nodes', 'abc')"/>
which applies templates to all <node>'s with a value of ID attribute of
'abc'. |
4. | Unique values across multiple documents |
| Dimitre Novatchev.
> > I want to create an index across multiple XML
> > documents in order to check the name uniqueness of the
> > element "Member".
> >
>
> I think that to check uniqueness across multiple documents in 1.0, the
> only way is to copy the relevant data into a new temporary document, and
> then use the standard grouping (or deduplicating) techniques on that.
Not really. This can be achieved using the "makeDistinct" template from FXSL
without creating a new temporary document. The solution was first described on this list almost two years ago:
http://sources.redhat.com/ml/xsl-list/2001-12/msg00806.html |
5. | Mixing generate-id and existing id values |
| David Tolpin
> generate-id() is not guaranteed to generate an identifier unique
> for the document.
> It is only guaranteed to produce a different string for each node.
> If another node already
> has the same id as one just generated, there will be
> duplicate identifiers in the result.
>
Here is one that will do the job <xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">
<xsl:key name="ids" match="//*" use="@id"/>
<xsl:template match="*">
<xsl:copy>
<xsl:if test="not(@id)">
<xsl:attribute name="id">
<xsl:call-template name="generate-unique-id">
<xsl:with-param name="prefix" select="generate-id()"/>
</xsl:call-template>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="*|@*|text()"/>
</xsl:copy>
</xsl:template>
<xsl:template name="generate-unique-id">
<xsl:param name="prefix"/>
<xsl:param name="suffix"></xsl:param>
<xsl:variable name="id" select="concat($prefix,$suffix)"/>
<xsl:choose>
<xsl:when test="key('ids',$id)">
<xsl:call-template name="generate-unique-id">
<xsl:with-param name="prefix" select="$prefix"/>
<xsl:with-param name="suffix" select="concat($suffix,'x')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$id"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*|text()">
<xsl:copy/>
</xsl:template>
</xsl:transform>
|