Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: Merge two XML docments with XSLT

From: "Marrow" <m--a-r-r-o-w@--------------------.--->
To: NULL
Date: 9/11/2004 11:42:00 AM
Hi Daniel,

> This probably a dumb question but is
>
> <xsl:apply-templates select="@* | node()"/>
>
> The same as
>
> <xsl:apply-templates select="node()"/>
>
> Since node() gets all child nodes of any type?
>

No, not a dumb question - the terminology can get a little misleading.  When
you are taking about an XML DOM then 'node' means every component part of
the document (much in the common sense of the word 'node').  But when you
are talking about XPath then there are 3 different axis - the node axis, the
attribute axis and the namespace axis.  The node test node() only tests for
items on the node axis - which are:- elements, text nodes, comments,
processing instructions and that special one we call the document root node
(not to be confused with the document root element).

So, in short, no those two expressions are not the same...

 <xsl:apply-templates select="@* | node()"/>
selects all nodes on the node axis (elements, text nodes, comments, pi's and
doc root node) unioned with everything on the attribute axis.

whereas...
 <xsl:apply-templates select="node()"/>
only selects nodes on the node axis but no attributes.


[from your other posting]...

> What does this code segment do?
>
> <xsl:template match="@* | text() | comment() |
> processing-instruction()"><!--  -->
>   <xsl:copy/><!-- Creates a copy of the current node (without child nodes
> and attributes) -->
> </xsl:template>
> </xsl:stylesheet>
>
> It has no mode so im not sure how it is called by the other templates. If
it
> applies for all attributes, text, cmments and processing-instructions in
the
> souce document then what keeps it from over writing the work of the other
> templates?

It copies everything that was caught by that template - specifically, it
copies all attributes, text nodes, comments and processing instructions that
were caught by this template.  Matched templates are not 'called' as such -
they are matched against node-sets that are pushed out by an
<xsl:apply-templates> (or <xsl:apply-imports>).  You can imagine the
<xsl:apply-templates> as something like throwing everything it selects up in
the air - and the right templates will know which of those to catch.

> what keeps it from over writing the work of the other templates?

Because templates are matched based primarily on a 'best match' priority
(there are other considerations too - but that will get far too complicated
here).  So a template that more specifically matches something will override
a template that has a more 'generic' match.
As a simple example, if you did...
  <xsl:apply-templates select="foo"/>
and had two templates...
  <xsl:template match="*">
    ...
  </xsl:template>
  <xsl:template match="foo">
    ...
  </xsl:template>
then it would be the second of those templates that would be applied -
because it has a more specific match.


> Is there anything else that needs to be done besides changing the maps
> variable?
>     Would like to ensure that
>         - <top> is the root node of the resulting document
>         - <mapswithdata> wrapper is not in resulting document
>         - <maps> mapping data does not appear in the resulting document
>         - The root node of the resulting document remains <top>

OK, 3 of those are more or less the same thing - ensuring that <top> is the
document root element of the output.  The other is ensuring that
<mapswithdata> (and its children) does not appear in the output.
You are dealing with a push processing stylesheet (push just means we are
pushing nodes out for processing using <xsl:apply-templates> - as opposed to
pulling nodes using <xsl:for-each>).  The stylesheet is we already have is
also based loosely on an idenity transform (an identity transform is one
that, for the most part, copies the input document as is but with some
exception alterations).  Bearing this in mind - to perform almost any
'special' requirements is about adding an appropriate template that matches
the node that is to have special processing and providing the logic that
handles it.
So, taking the first requirement - "ensure that <top> is the root node of
the resulting document" - we need to catch whatever is the current input
document root element and ensure that <top> is output instead, and then
continue processing the rest of the document, e.g. adding a template that
looks like...
  <xsl:template match="/*">
    <top>
      <xsl:apply-templates/>
    </top>
  </xsl:template>
and also ensuring that the <top> element is the document root element in the
output.  Well, we have already ensured that <top> is the document root
element of the output - so we just need to ensure that the <top> element of
the input document is not repeated in the output, e.g.
  <xsl:template match="top">
    <xsl:apply-templates/>
  </xsl:template>

Secondly, the requirement "ensure that <maps> mapping data does not appear
in the resulting document" - again, it is a matter of adding a template that
catches this element and prevents it being copied into the output, e.g.
  <xsl:template match="maps"/>
(Note that the template tag is self-closing - so although the template will
catch the <maps> element it is entirely empty so will do nothing further
with that element).

So the final stylesheet (hmmm, see also notes on .Net bug below) is as
follows...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="maps" select="/mapswithdata/maps/element"/>

<xsl:template match="/">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="*">
  <xsl:variable name="this-element-map" select="$maps[@source =
local-name(current())]"/>
  <xsl:choose>
    <xsl:when test="$this-element-map">
      <xsl:element name="{$this-element-map/@target}">
        <xsl:apply-templates select="@*" mode="mapped">
          <xsl:with-param name="attributes-map"
select="$this-element-map/attribute"/>
        </xsl:apply-templates>
        <xsl:apply-templates/>
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="/*">
  <top>
    <xsl:apply-templates/>
  </top>
</xsl:template>

<xsl:template match="top">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="maps"/>

<xsl:template match="@*" mode="mapped">
  <xsl:param name="attributes-map"/>
  <xsl:variable name="this-attribute-map" select="$attributes-map[@source =
local-name(current())]"/>
  <xsl:if test="$this-attribute-map">
    <xsl:attribute name="{$this-attribute-map/@target}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:if>
</xsl:template>

<xsl:template match="@* | text() | comment() | processing-instruction()">
  <xsl:copy/>
</xsl:template>
</xsl:stylesheet>


OK, finally...

> When I test this using saxon or the marrowsoft.com client it works, but
when
> I test it with C# System.Xml.Xsl.XslTransform it does not work. Is there
> some modification that must be done to this to make it work w/ C#
> System.Xml.Xsl.XslTransform? The part that I think is not getting
processed
> by the C# System.Xml.Xsl.XslTransform is <xsl:template match="@*"
> mode="mapped">

Yes, you are right.  There seems to be a bug in .Net casuing this stylesheet
not to work as it would be expected.  I haven't been able to come with with
a shorter example that illustrates this bug - and I believe that something
similar to this was reported recently on one of the newsgroups.  Anyway,
that is up to MS to determine the problem and get it fixed!  I have even
tried a few work arounds and all seem to fail with .Net!


HTH
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator





transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent