在XSL合并时,将具有特定名称的元素N与其他XML的元素N匹配

时间:2013-01-28 13:09:41

标签: xml xslt xpath merge

我需要合并两个XML文档。

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

第一个是原始XML。请求已被撤出并发送到系统,接下来是响应。现在我需要合并这两个并将请求N与响应N匹配,这样我就可以从响应中提取一些信息。 XSL在A.xml上运行并获取B.xml作为参数。首先,我只想在A.xml中的请求中创建B.xml中正确响应的副本。

我遇到的问题是我认为我可以使用position(),但意识到这不起作用,因为cm:Request元素与其他元素混合在一起。还有其他方法可以用来匹配这些吗?

这就是我的尝试:

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

这里有两个问题。

  1. 首先position()不匹配。有没有办法获得你所在的cm:Request元素的数量/位置,而不是所有兄弟元素的数量/位置?因此,如果第一个cm:Request前面有任何元素,那么第一个position()总是给出1。
  2. 其次我出于某种原因在每个请求中获取所有响应的副本。如果我使用例如1更改blah,我只会在每个请求中获得第一个响应的副本。我在这做错了什么?
  3. 希望有人知道我应该在这做什么,因为我现在有点空白而且我的Google-fu让我失望:P

    总结,如何将第n个元素与名称{{1}}与参数node-set中的第n个子元素进行匹配?

2 个答案:

答案 0 :(得分:1)

这是怎么回事:

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

解释一下:

  
    

2.其次,我出于某种原因获得每个请求中所有响应的副本。如果我用例如1更改position(),我只会在每个请求中获得第一个响应的副本。我在这里做错了什么?

  

在这种情况下,position()的行为实际上与您的想法不同。如果您在该模板中执行此操作:

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

然后 $pos将拥有与其所有兄弟姐妹相关的当前cm:Request的位置,但在此处:

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

position()正在上下文$responses/*[1]/*中进行评估。因此,对于第一个<response>,此评估为$responses/*[1]/*[1],对于第二个响应,此评估为$responses/*[1]/*[2],因此两者始终处于选中状态。

答案 1 :(得分:1)

一种方法应该是

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