【问题标题】:Copying a Child Node into its Parent's Sibling's Child Node将子节点复制到其父兄弟的子节点
【发布时间】:2016-07-21 10:27:22
【问题描述】:

我刚刚开始学习使用 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>

我需要做的是将 &lt;b2_2&gt; 节点及其内容从 &lt;c&gt; 节点移动到 特定 &lt;b&gt; 节点的子节点 - 值为 b/b1等于c/b1的值。
因此,基本上,如果父节点共享相同值的特定元素,则将子节点移动到其表兄弟节点。

期望的结果:

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

此代码完成了部分工作 - 它将目标 &lt;b2_2&gt; 节点移动到目标 &lt;b&gt; 节点,同时清理冗余的 &lt;c&gt; 节点。

我现在得到的

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

我可以看到如何使用两个 XSLT 文件分两步进行所需的转换,但我觉得解决方案很简单而且表面上很简单。无法确定将目标节点放置到它应该在的子节点的方式,因此将不胜感激任何正确方向的提示。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    怎么样:

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

    【讨论】:

    • 感谢您如此迅速的答复!你是对的,我必须通过b1 值链接节点。很抱歉没有首先澄清它,但b2 已经有除b2_2 之外的其他元素,并且您的代码在此过程中清除了它们。我编辑了问题,以便更清楚地说明这一点。
    • 简单修复 - 见上文。
    • 非常感谢,Michael,您的回答使我朝着正确的方向前进,在研究了 xsl:key 使用规则后,我成功地将您提供的解决方案应用于实际数据。
    猜你喜欢
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多