Match the N element with a certain name to the N element of another XML during the XSL merge

advertisements

I have two XML documents I need to merge.

<!-- A.xml -->
<cm:Process>
    <cm:Other />
    <cm:Elements />
    <cm:Request>
        <!-- stuff -->
    </cm:Request>
    <cm:ElementCouldBeHereToo />
    <cm:Request>
        <!-- stuff -->
    </cm:Request>
</cm:Process>

<!-- B.xml -->
<gateway-orders>
    <response>
        <status />
    </response>
    <response>
        <status />
    </response>
</gateway-orders>

The first is the original XML. The requests has been pulled out and sent to a system and the next is the responses. Now I need to merge these two and match request N with response N so I can pull in some info from the responses. The XSL work on A.xml and get B.xml as a parameter. To begin with I'm just trying to create a copy of the correct response in B.xml inside the request in A.xml.

The problem I have is that I thought I could use position(), but realized that won't work since the cm:Request elements are mixed with other elements. Is there another way I can use to match up these somehow?

This is what I tried:

<xsl:import href="identity-transform.xsl" />

<xsl:param name="responses" />

<xsl:template match="cm:Request">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
        <xsl:apply-templates select="$responses/*[1]/*[position()]" />
    </xsl:copy>
</xsl:template>

There are two problems here.

  1. First of all the position() won't match up. Is there a way to get the number/position of cm:Request elements you're at rather than the number/position of all sibling elements? So that the first cm:Request always gives 1 irregardless of if it has any elements in front of it.
  2. Secondly I for some reason get a copy of all responses inside each request. If I change position() with for example 1, I only get a copy of the first response in each request. What am I doing wrong here?

Hoping someone knows what I should do here, cause I'm a bit blank right now and my Google-fu is failing me :P

So to sum up, how can I match up the nth element with name blah with the nth child in a parameter node-set?


How's this:

<xsl:template match="cm:Request">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
        <xsl:variable name="reqNum" select="count(preceding-sibling::cm:Request | .)" />
        <xsl:apply-templates select="$responses/*[1]/response[$reqNum]" />
    </xsl:copy>
</xsl:template>

To explain this:

2.Secondly I for some reason get a copy of all responses inside each request. If I change position() with for example 1, I only get a copy of the first response in each request. What am I doing wrong here?

In this case, position() is actually behaving differently from how you think it is. If you did this in that template:

<xsl:variable name="pos" select="position()" />

Then $pos would have the position of the current cm:Request in relation to all of its siblings, but here:

$responses/*[1]/*[position()]

position() is being evaluated in the context $responses/*[1]/*. So for the first <response> this evaluates to $responses/*[1]/*[1] and for the second response, this evaluates to $responses/*[1]/*[2], hence both are always selected.