This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[no subject]


Hi All,
I've a problem while using MSXML3 or MSXML4 as my processor which I do not get when I use Saxon or Xalan-J processors. The following are the input files and the output files. Though it's lengthy (because of the files that are included), it's might not be a big one. Please can some one explain me why MSXML does create this problem?

Here I am merging 2 xml files using an XSL file (courtesy: Oliver)

---------------------------
InputFile_1.xml
---------------------------
<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:m="http://www.xyz.com/m";>
<Header>
<Version>1.0</Version>
</Header>
<Message>
<Type>Response</Type>
<SubType>CALCULATION</SubType>
<Calculate>
<Data>
<A>
<Time>
<B Unit="XY">+21.0</B>
<C Unit="XY">+5.0</C>
<D>0</D>
</Time>
</A>
</Data>
</Calculate>
</Message>
</Root>
------------------------------------
InputFile_2.xml
------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Message>
<Calculate>
<Data>
<A>
<Time>
<BDesc stage="LM">Some Text 1</BDesc>
<CDesc stage="LM">Some Text 2</CDesc>
<D>0</D>
</Time>
</A>
</Data>
</Calculate>
</Message>
</Root>
--------------------------------
Merger.xsl
-------------------------------
<?xml version="1.0"?>
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:m="http://www.xyz.com/merge";
exclude-result-prefixes="m">
<!-- Normalize the contents of text, comment, and processing-instruction
nodes before comparing?
Default: yes -->
<xsl:param name="normalize" select="'yes'" />
<!-- Don't merge elements with this (qualified) name -->
<xsl:param name="dontmerge" />
<!-- If set to true, text nodes in file1 will be replaced -->
<xsl:param name="replace" select="false()" />
<!-- Variant 1: Source document looks like
<?xml version="1.0"?>
<merge xmlns="http://www.xyz.com/merge";>
<file1>file1.xml</file1>
<file2>file2.xml</file2>
</merge>
The transformation sheet merges file1.xml and file2.xml.
-->
<xsl:template match="m:merge" >
<xsl:variable name="file1" select="string(m:file1)" />
<xsl:variable name="file2" select="string(m:file2)" />
<xsl:message>
<xsl:text />Merging '
<xsl:value-of select="$file1" />
<xsl:text />' and '
<xsl:value-of select="$file2"/>'
<xsl:text />
</xsl:message>
<xsl:if test="$file1='' or $file2=''">
<xsl:message terminate="yes">
<xsl:text>No files to merge specified</xsl:text>
</xsl:message>
</xsl:if>
<xsl:call-template name="m:merge">
<xsl:with-param name="nodes1" select="document($file1,/*)/node()" />
<xsl:with-param name="nodes2" select="document($file2,/*)/node()" />
</xsl:call-template>
</xsl:template>
<!-- Variant 2:
The transformation sheet merges the source document with the
document provided by the parameter "with".
-->
<xsl:param name="with" select="'./InputFile_2.xml'"/>
<xsl:template match="*">
<xsl:message>
<xsl:text />Merging input with '
<xsl:value-of select="$with"/>
<xsl:text>'</xsl:text>
</xsl:message>
<xsl:if test="string($with)=''">
<xsl:message terminate="yes">
<xsl:text>No input file specified (parameter 'with')</xsl:text>
</xsl:message>
</xsl:if>
<xsl:call-template name="m:merge">
<xsl:with-param name="nodes1" select="/node()" />
<xsl:with-param name="nodes2" select="document($with,/*)/localText/node()" />
</xsl:call-template>
</xsl:template>
<!-- ============================================================== -->
<!-- The "merge" template -->
<xsl:template name="m:merge">
<xsl:param name="nodes1" />
<xsl:param name="nodes2" />

<xsl:choose>
<!-- Is $nodes1 resp. $nodes2 empty? -->
<xsl:when test="count($nodes1)=0">
<xsl:copy-of select="$nodes2" />
</xsl:when>
<xsl:when test="count($nodes2)=0">
<xsl:copy-of select="$nodes1" />
</xsl:when>

<xsl:otherwise>
<!-- Split $nodes1 and $nodes2 -->
<xsl:variable name="first1" select="$nodes1[1]" />
<xsl:variable name="rest1" select="$nodes1[position()!=1]" />
<xsl:variable name="first2" select="$nodes2[1]" />
<xsl:variable name="rest2" select="$nodes2[position()!=1]" />

<!-- Determine type of node $first1 -->
<xsl:variable name="type1">
<xsl:apply-templates mode="m:detect-type" select="$first1" />
</xsl:variable>


<!-- Compare $first1 and $first2 -->
<xsl:variable name="diff-first">
<xsl:call-template name="m:compare-nodes">
<xsl:with-param name="node1" select="$first1" />
<xsl:with-param name="node2" select="$first2" />
</xsl:call-template>
</xsl:variable>

<xsl:choose>
<!-- $first1 != $first2 -->
<xsl:when test="$diff-first='!'">
<!-- Compare $first1 and $rest2 -->
<xsl:variable name="diff-rest">
<xsl:for-each select="$rest2">
<xsl:call-template name="m:compare-nodes">
<xsl:with-param name="node1" select="$first1" />
<xsl:with-param name="node2" select="." />
</xsl:call-template>
</xsl:for-each>
</xsl:variable>

<xsl:choose>
<!-- $first1 is in $rest2 and
$first1 is *not* an empty text node -->
<xsl:when test="contains($diff-rest,'=') and
not($type1='text')">
<!-- determine position of $first1 in $nodes2
and copy all preceding nodes of $nodes2 -->
<xsl:variable name="pos"
select="string-length(substring-before(
$diff-rest,'=')) + 2" />
<xsl:copy-of select="$nodes2[position() &lt; $pos]" />
<!-- merge $first1 with its equivalent node -->
<xsl:choose>
<!-- Elements: merge -->
<xsl:when test="$type1='element'">

<xsl:element name="{name($first1)}"
namespace="{namespace-uri($first1)}">
<xsl:copy-of select="$first1/namespace::*" />
<xsl:copy-of select="$first2/namespace::*" />
<xsl:copy-of select="$first2/@*" />
<xsl:copy-of select="$first1/@*" />
<xsl:call-template name="m:merge">
<xsl:with-param name="nodes1"
select="$first1/node()" />
<xsl:with-param name="nodes2"
select="$nodes2[position()=$pos]/node()" />
</xsl:call-template>
</xsl:element>
</xsl:when>
<!-- Other: copy -->
<xsl:otherwise>
<xsl:copy-of select="$first1" />
</xsl:otherwise>
</xsl:choose>

<!-- Merge $rest1 and rest of $nodes2 -->
<xsl:call-template name="m:merge">
<xsl:with-param name="nodes1" select="$rest1" />
<xsl:with-param name="nodes2"
select="$nodes2[position() &gt; $pos]" />
</xsl:call-template>
</xsl:when>

<!-- $first1 is a text node -->
<xsl:when test="$type1='text'">
<xsl:call-template name="m:merge">
<xsl:with-param name="nodes1" select="$rest1" />
<xsl:with-param name="nodes2" select="$nodes2" />
</xsl:call-template>
</xsl:when>


<!-- else: $first1 is not in $rest2 or
$first1 is an empty text node -->
<xsl:otherwise>
<xsl:copy-of select="$first1" />
<xsl:call-template name="m:merge">
<xsl:with-param name="nodes1" select="$rest1" />
<xsl:with-param name="nodes2" select="$nodes2" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>

<!-- else: $first1 = $first2 -->
<xsl:otherwise>
<xsl:choose>
<!-- Elements: merge -->
<xsl:when test="$type1='element'">
<xsl:element name="{name($first1)}"
namespace="{namespace-uri($first1)}">
<xsl:copy-of select="$first1/namespace::*" />
<xsl:copy-of select="$first2/namespace::*" />
<xsl:copy-of select="$first2/@*" />
<xsl:copy-of select="$first1/@*" />
<xsl:call-template name="m:merge">
<xsl:with-param name="nodes1" select="$first1/node()" />
<xsl:with-param name="nodes2" select="$first2/node()" />
</xsl:call-template>
</xsl:element> </xsl:when>
<!-- Other: copy -->
<xsl:otherwise>
<xsl:copy-of select="$first1" />
</xsl:otherwise>
</xsl:choose>


<!-- Merge $rest1 and $rest2 -->
<xsl:call-template name="m:merge">
<xsl:with-param name="nodes1" select="$rest1" />
<xsl:with-param name="nodes2" select="$rest2" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Comparing single nodes:
if $node1 and $node2 are equivalent then the template creates a
text node "=" otherwise a text node "!" -->
<xsl:template name="m:compare-nodes">
<xsl:param name="node1" />
<xsl:param name="node2" />
<xsl:variable name="type1">
<xsl:apply-templates mode="m:detect-type" select="$node1" />
</xsl:variable>
<xsl:variable name="type2">
<xsl:apply-templates mode="m:detect-type" select="$node2" />
</xsl:variable>

<xsl:choose>
<!-- Are $node1 and $node2 element nodes with the same name? -->
<xsl:when test="$type1='element' and $type2='element' and
local-name($node1)=local-name($node2) and
namespace-uri($node1)=namespace-uri($node2) and
name($node1)!=$dontmerge and name($node2)!=$dontmerge">=</xsl:when>


<!-- Otherwise: different node types or different name/content -->
<xsl:otherwise>!</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="m:detect-type">element</xsl:template>
<xsl:template match="text()" mode="m:detect-type">text</xsl:template>
<xsl:template match="comment()" mode="m:detect-type">comment</xsl:template>
<xsl:template match="processing-instruction()" mode="m:detect-type">pi</xsl:template>
</xsl:transform>

----------------------------------
Output.xml using Saxon or Xalan
----------------------------------
<?xml version="1.0" encoding="UTF-8" ?>
- <Root>
- <Header xmlns:m="http://www.xyz.com/m";>
<Version>1.0</Version>
</Header>
- <Message>
<Type xmlns:m="http://www.xyz.com/m";>Response</Type>
<SubType xmlns:m="http://www.xyz.com/m";>CALCULATION</SubType>
- <Calculate>
- <Data>
- <A>
- <Time>
<B xmlns:m="http://www.xyz.com/m"; Unit="XY">+21.0</B>
<C xmlns:m="http://www.xyz.com/m"; Unit="XY">+5.0</C>
<BDesc stage="LM">Some Text 1</BDesc>
<CDesc stage="LM">Some Text 2</CDesc>
<D>0</D>
</Time>
</A>
</Data>
</Calculate>
</Message>
</Root>
-----------------------------------------------
Output.xml using MSXML 3 or 4
---------------------------------
<?xml version="1.0" encoding="UTF-16" ?>
- <Root xmlns:m="http://www.xyz.com/m";>
- <Header>
<Version>1.0</Version>
</Header>
- <Message>
<Type>Response</Type>
<SubType>CALCULATION</SubType>
- <Calculate>
- <Data>
- <A>
- <Time>
<B Unit="XY">+21.0</B>
<C Unit="XY">+5.0</C>
<BDesc stage="LM">Some Text 1</BDesc>
<CDesc stage="LM">Some Text 2</CDesc>
<D stage="LM">0</D>
</Time>
</A>
</Data>
</Calculate>
</Message>
</Root>
-------------------------------------------

If you here, thanks for your patience. If you can notice, there is a very small difference in the above 2 output files. The element <<D>> has an attribute "stage" in the second one (using MSXML) where as it doesn't have any attribute and is copied down as expected in the first one (using Saxon or Xalan). Can someone explain me what's the reason behind this discrepancy.

Thanks,
Kalyan

XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]