Re: [xsl] Mixing sources to create a pattern

Subject: Re: [xsl] Mixing sources to create a pattern
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Mon, 22 Dec 2008 21:11:13 -0500
At 2008-12-22 20:03 -0600, Andrew Ferk wrote:
I have two standalone xml files, strucure.xml and data.xml.  I also
have the XSLT file layout.xsl.

layout.xsl is being applied to structure.xml, and data.xml is being
used in layout.xsl like below:

<xsl:variable name="data" select="document('data.xml')/data" />

In layout.xsl i'm in a loop below:

<xsl:for-each select="some_tag">
    <div id="{@id}" class="{$data/@id}">...</div>
</xsl:for-each>

So if structure.xml has <some_tag id="test_id" />
and data.xml has <data><test_id>test_class</test_id></data>
I want a transformation of <div id="test_id" class="test_class">...</div>.

In XSLT 1.0 or XSLT 2.0, using your variable:


<xsl:for-each select="some_tag">
    <div id="{@id}" class="{$data/*[name(.)=current()/@id]}">...</div>
</xsl:for-each>

In XSLT 1.0, using a key table instead of your variable:

<!--load up a key table with children of data, indexed by name-->
<xsl:key name="'data'" match="data/*" use="name(.)"/>

<xsl:for-each select="some_tag">
  <div id="{@id}">
    <xsl:variable name="id" select="@id"/>
    <xsl:for-each select="document('data.xml')">
       <xsl:attribute name="class">
          <xsl:value-of select="key('data',$id)"/>
       </xsl:attribute>
    </xsl:for-each>
    ...
  </div>
</xsl:for-each>

In XSLT 2.0 this is a lot tighter:

<!--load up a key table with children of data, indexed by name-->
<xsl:key name="'data'" match="data/*" use="name(.)"/>

<xsl:for-each select="some_tag">
    <div id="{@id}"
         class="{key('data',@id,document('data.xml'))}">...</div>
</xsl:for-each>

Don't worry about the repeated calls to the document() function, the processor knows not to go and fetch the XML document each time.

I do worry about your possible use of namespaces and the default namespace, but I'm assuming above you are doing everything in no namespace.

Why does this not work

Because of context and the addressing of elements vs. the addressing of attributes.


Where you say "$data/@id", that is the id= attribute of each element in the $data variable, not element children of $data elements whose name is that of an id= attribute.

and is their a solution to create a pattern
mixing these different xml sources?

In XSLT the term "pattern" is used for that subset of XPath expressions suitable for an attribute with match= properties. I don't see any solution involving nuances of patterns ... after all, only one node is being sent to the template rules at any one time, and it only comes from one of the two documents.


I hope this helps.

. . . . . . . . . Ken

--
Upcoming XSLT/XSL-FO, UBL and code list hands-on training classes:
:  Sydney, AU 2009-01/02; Brussels, BE 2009-03; Prague, CZ 2009-03
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video sample lesson:    http://www.youtube.com/watch?v=PrNjJCh7Ppg
Video course overview:  http://www.youtube.com/watch?v=VTiodiij6gE
G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal

Current Thread