将子节点复制到其父节点的子节点中

时间:2016-07-21 10:27:22

标签: xml xslt

我刚刚开始学习使用XLS进行XML到XML转换,所以这可能是一个新手,但似乎无法在单个XSLT迭代中获得我想要的转换,并且无法找到任何内容在这件事上。
这就是我所拥有的:

源XML:

<data>
<a/>
<b>
  <b1>ID#1</b1>
  <b2>
    <b2_1/>
  </b2>
</b>
<c>
  <b1>ID#1</b1>
  <b2_2/>
</c>
<!-- b and c nodes keep repeating with the same structure for different b1 IDs -->
</data>

我需要做的是将<b2_2>节点及其内容从<c>节点移动到特定 <b>节点的子节点 - b/b1的值等于c/b1的值 因此,如果他们的父母共享一个具有相同价值的特定元素,可以将Child节点移动到它的Cousin节点。

期望的结果:

<data>
<a/>
<b>
  <b1>ID#1</b1>
  <b2>
    <b2_1/>
    <b2_2/>
  </b2>
</b>
</data>

当前的XSLT:

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="b">
  <xsl:variable name="id1" select="b1"  />
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
    <xsl:apply-templates select="following-sibling::c[b1=$id1]/b2_2"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="c"/>

此代码执行部分工作 - 它将目标<b2_2>节点移动到目标<b>节点,同时清除冗余的<c>节点。

我现在得到什么

<data>
<a/>
<b>
  <b1>ID#1</b1>
  <b2>
    <b2_1/>
  </b2>
  <b2_2/>
</b>
</data>

我可以看到如何使用两个XSLT文件分两步完成所需的转换,但我觉得解决方案很简单且表面上看。无法确定将目标节点放置到应该位于的子节点的方式,因此会理解正确方向上的任何提示。

1 个答案:

答案 0 :(得分:0)

怎么样:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="b2">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:copy-of select="../following-sibling::c[1]/b2_2"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="c"/>

</xsl:stylesheet>

或者,如果您希望按b1值链接:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="c" match="c" use="b1" />

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="b2">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:copy-of select="key('c', ../b1)/b2_2"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="c"/>

</xsl:stylesheet>