xsl-list
[Top] [All Lists]

Re: [xsl] Merging attributes in one XML file with node values in another (identical structure)

2006-06-22 07:48:15
Chris,

Still thinking ... I believe if you really have to have one pass, the merge is still possible using a "double traversal" passing parameters to track where you are in each document as you go. (I even think I've done this. But it makes my head hurt.) If you can pipeline using XSLT 2.0, a node-set() extension function in 1.0, or two passes, I'd really recommend the technique I suggest below, which is something of a "Gordian knot" solution.

In the meantime, maybe an intrepid XSLTer is even now working out the double-traversal.
:-)

Cheers,
Wendell

At 10:26 AM 6/22/2006, you wrote:
Chris,

The hard part of this problem is identifying which node in your second document is the "same" node as a given node in your first document.

This is much easier if you can pre-process one or both documents (pipeline). The first pass could label the nodes in one of the documents to allow them to be looked up in the merge pass. If it were me, I'd probably label them with an XPath to identify each node uniquely (partly since I've done this before and know how :-). Using this approach, a simple labeling stylesheet would look like this:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

    <xsl:template match="*">
      <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:attribute name="xpath">
<!-- assuming your input doesn't already have 'xpath' attributes -->
          <xsl:for-each select="ancestor-or-self::*">
            <xsl:text>/</xsl:text>
            <xsl:value-of select="name()"/>
            <xsl:if test="count(../*[name()=name(current())]) &gt; 1">
              <xsl:text>[</xsl:text>
              <xsl:number/>
              <xsl:text>]</xsl:text>
            </xsl:if>
          </xsl:for-each>
        </xsl:attribute>
        <xsl:apply-templates/>
      </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Run this over your input documents and the results will be much easier to merge.

In the second phase, I'd probably write a key to retrieve my nodes efficiently using their @xpath values.

In XSLT 2.0 you could do this in a single stylesheet.

I hope that helps,
Wendell

At 09:59 AM 6/22/2006, you wrote:
O.K. here's my question.  It seems like it should be simple but I can't
figure it out.
I have two XML files. One with data in the node values, and one with
data in attributes. They have the same exact structure.

<a>
   <b>
      <node>1</node>
   </b>
   <c>
      <d>
         <node>2</node>
      </d>
   </c>
</a>

... and ...

<a>
   <b val="x">
      <node width="10"/>
   </b>
   <c>
      <d val="z">
         <node height="15"/>
      </d>
   </c>
</a>

As you can see the word "node" node appears at /a/b/node and a/c/d/node
but has two distinct values and attributes.
Is there a way to transform the first one with XSLT to produce the
following results:

<a>
   <b val="x">
      <node width="10">1</node>
   </b>
   <c>
      <d val="z">
         <node height="15">2</node>
      </d>
   </c>
</a>

...essentially combining the node values of one file with the attributes
in the other.
I've really been struggling with this. I was able to do it with
recursion, but I'm looking for a way to do it without using recursive
procedures. I don't think it's possible. Is it?


--~------------------------------------------------------------------
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>
--~--


--~------------------------------------------------------------------
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>
--~--