在不同的父级下复制子节点

时间:2013-10-14 12:24:34

标签: xml xslt

我是XSLT的新手并且遇到了这个问题 输入XML

<Root>
 <Family>
   <Entity>
     <SomeElement1/>
     <Child1>
       <Element1/>
     </Child1>
     <Child2>
       <Element2/>
     </Child2>
     <Entity>
     <SomeElement1/>
     <Child1>
       <Element111/>
     </Child1>
     <Child2>
       <Element222/>
     </Child2>
   </Entity>
  </Entity>
 </Family>
</Root>

输出Xml

<Response>
 <EntityRoot>
  <SomeElement1/>
 </EntityRoot>

 <Child1Root>
   <Element1>
 </Child1Root>

 <Child2Root>
   <Element2>
 </Child2Root>

 <MetadataEntityRoot>
  <SomeElement1/>
 </MetadataEntityRoot>

 <Child1Root>
   <Element111>
 </Child1Root>

 <Child2Root>
   <Element222>
 </Child2Root>
</Response>

我知道如何从输入xml中复制所有内容。但不确定如何排除子元素,然后在不同的根元素中再次复制它们。

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

根据给定的答案尝试

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
   </xsl:template>
    <xsl:template match="Entity">
      <EntityRoot>
        <xsl:apply-templates select="@* | node()[not(self::Child1 | self::Child2)]" />
      </EntityRoot>
      <xsl:apply-templates select="Child1 | Child2" />
    </xsl:template>
    <xsl:template match="Child1">
      <Child1Root><xsl:apply-templates select="@*|node()" /></Child1Root>
    </xsl:template>
    <xsl:template match="Child2">
      <Child2Root><xsl:apply-templates select="@*|node()" /></Child2Root>
    </xsl:template>
</xsl:stylesheet>

但输出为:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
 <Family>
   <EntityRoot>
     <SomeElement1/>
   </EntityRoot>
   <Child1Root>
       <Element1/>
    </Child1Root>
    <Child2Root>
       <Element2/>
    </Child2Root>
 </Family>
</Root>

1 个答案:

答案 0 :(得分:2)

除了您已经拥有的“复制所有内容”标识模板之外,您只需添加与要以不同方式处理的元素匹配的特定模板。要将Child1重命名为Child1Root,您可以使用

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

同样将Child2重命名为Child2Root,将Root重命名为Response。对于Entity,您可以将该过程视为创建EntityRoot包含(应用模板的结果)除 Child1和Child2之外的所有子元素,然后将模板应用于这些之后两个,在EntityRoot元素之外:

<xsl:template match="Entity">
  <EntityRoot>
    <xsl:apply-templates select="@* | node()[not(self::Child1 | self::Child2)]" />
  </EntityRoot>
  <xsl:apply-templates select="Child1 | Child2" />
</xsl:template>

要完全剥离图层(在这种情况下为Family)但仍然包含其子图层,您可以使用不带copy的模板:

<xsl:template match="Family">
  <xsl:apply-templates />
</xsl:template>