xsl-list
[Top] [All Lists]

Re: [xsl] Follow path in source-xml according to another source-document

2007-11-22 20:53:44
Please try the following stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                       version="1.0">
        
  <xsl:output method="text" />

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

  <!-- matches the leaf element -->
  <xsl:template match="*[not(node())]">
    <xsl:variable name="result">
      <xsl:call-template name="getText">
        <xsl:with-param name="largeDoc" select="$largeDoc/*" />
        <xsl:with-param name="elem" select="." />
      </xsl:call-template>
    </xsl:variable>
    <xsl:value-of select="normalize-space($result)" /><xsl:text>&#xa;</xsl:text>
  </xsl:template>

  <xsl:template match="text()" />

  <xsl:template name="getText">
    <xsl:param name="largeDoc" />
    <xsl:param name="elem" />

    <xsl:choose>
      <xsl:when test="(local-name($largeDoc) = local-name($elem)) and
($largeDoc/@id = $elem/@id)">
        <xsl:value-of select="$largeDoc" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:for-each select="$largeDoc/*">
          <xsl:call-template name="getText">
             <xsl:with-param name="largeDoc" select="." />
             <xsl:with-param name="elem" select="$elem" />
          </xsl:call-template>
        </xsl:for-each>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

PS: This stylesheet is applied to the "light" input XML. And the other
XML is named as, large.xml.
There are some approximations for the input structure, and also some
redundant processing.

On Nov 22, 2007 10:27 PM,  <christoph(_dot_)naber(_at_)daimler(_dot_)com> wrote:
Hello list,

I want to follow a path in a given source-document, which is a
"light"-version of another source document.

The used processor is xsltproc, but the stylesheet is intended to run on
Xalan so I have to use XSLT 1.0. The input-file-size will be up to 5 MB.

Example "light" input XML
<root>
       <elem1 id="one">
               <elem2 id="two">
                       <elem4 id="three_three" />
               </elem2>
               <elem3 id="six">
                       <elem5 id="seven" />
               </elem3>
       </elem1>
</root>

Example "large" input XML
<root>
       <elem1 id="one">
               <elem2 id="two">
                       <elem4 id="three_one" />
                       <elem4 id="three_two" />
                       <elem4 id="three_three">
                               Here is the data of three_three
                       </elem4>
                       <elem4 id="three_four" />
               </elem2>
               <elem3 id="four">
                       <elem5 id="five" />
               </elem3>
               <elem3 id="six">
                       <elem5 id="seven" >
                               Here is the data of seven
                       </elem5>
               </elem3>
               <elem3 id="eight">
                       <elem5 id="nine" />
               </elem3>
       </elem1>
</root>

Desired output:
Here is the data of three_three
Here is the data of seven

This is the stylesheet that I managed to write so far. But I have no idea
if this is the XSL-way to perform such a task.

<xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
       xmlns:exsl="http://exslt.org/common";>
       <xsl:output method="xml" indent="yes"/>

       <xsl:param name="lightdoc" select="string('light.xml')" />

       <xsl:template match="/" >
               <xsl:apply-templates select="root" >
                       <xsl:with-param name="light"
select="document($lightdoc)/root" />
               </xsl:apply-templates>
       </xsl:template>


       <xsl:template match="node()" >
               <xsl:param name="light" />
               <xsl:variable name="large" select="current()" />

               <xsl:choose>
                       <!-- We dont want to match textnodes or
processing-instructions -->
                       <xsl:when test="count($light/*) > 0" >
                               <xsl:for-each select="$light/*">
                                       <!-- not sure if I have to use
node-set here -->
                                       <xsl:apply-templates
select="exsl:node-set($large)/node()[(_at_)id = current()/@id]" >
                                               <xsl:with-param
name="light" select="current()" />
                                       </xsl:apply-templates>
                               </xsl:for-each>
                       </xsl:when>
                       <xsl:otherwise>
                               <xsl:value-of select="$large/text()" />
                       </xsl:otherwise>
               </xsl:choose>

       </xsl:template>

</xsl:stylesheet>

Any insight, eg. search items would be appreciated.

Greetings
Christoph Naber


-- 
Regards,
Mukul Gandhi

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>