【问题标题】:Aggregate multiple nodes to a single node in XSLT将多个节点聚合到 XSLT 中的单个节点
【发布时间】:2014-08-27 04:11:37
【问题描述】:

这是我需要使用 XSLT 转换的 XML 源代码

<?xml version="1.0" encoding="UTF-8"?>
<tns:Grand_Parent_XML xmlns:tns="">
  <GrandParent>
    <Parent>
        <Child>
            <Age>3</Age>
        </Child>
        <Child>
            <Gender>Male</Gender>
        </Child>
        <Child>
            <Name>Todd</Name>
        </Child>
        <Other>1234</Other>
    </Parent>
  </GrandParent>
</tns:Grand_Parent_XML>

这是通过 XSLT 转换后所需的输出

<?xml version="1.0" encoding="UTF-8"?>
<tns:Grand_Parent_XML xmlns:tns="">
  <GrandParent>
    <Parent>
        <Child>
            <Age>3</Age>
            <Gender>Male</Gender>
            <Name>Todd</Name>
        </Child>
        <Other>1234</Other>
    </Parent>
  </GrandParent>
</tns:Grand_Parent_XML>

这就是实际发生的事情......

<?xml version="1.0" encoding="UTF-8"?>
<tns:Grand_Parent_XML xmlns:tns="">
  <GrandParent>
    <Child>
        <Age>3</Age>
        <Gender>Male</Gender>
        <Name>Todd</Name>
    </Child>
  </GrandParent>
</tns:Grand_Parent_XML>

我正在使用这个 XSLT...

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="">
       <xsl:template match="Grand_Parent_XML/GrandParent/Parent">
         <Child>
           <xsl:for-each select="Child">
             <xsl:if test="Age !=''">
               <Age><xsl:value-of select="Age"/></Age>
             </xsl:if>
             <xsl:if test="Gender !=''">
               <Gender><xsl:value-of select="Gender"/></Gender>
             </xsl:if>
             <xsl:if test="Name !=''">
               <Name><xsl:value-of select="Nanme"/></Name>
             </xsl:if>
           </xsl:for-each> 
         </Child>
       </xsl:template>               
</xsl:stylesheet>

目前我对 XSLT 知之甚少,如果能得到任何帮助,我将不胜感激。使用我创建的 XSLT,父级被子级覆盖,这不应该是这种情况。此外,Parent 的其他子节点,即 Other 被删除。我使用的实际 XML 的字段比我在这里包含的要多得多。我可以选择手动将所有节点包含在 XSLT 中,但我觉得有一种更有效的方法可以做到这一点。谢谢!

【问题讨论】:

  • "这就是实际发生的事情......" 不,这不是使用您发布的代码发生的事情。

标签: xml xslt


【解决方案1】:

这是一种适用于各种不同输入的通用方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*" />
  <xsl:key name="kNamedSiblings" match="*" 
           use="concat(generate-id(..), '+', name())"/>

  <xsl:template match="*">
      <xsl:copy>
        <xsl:apply-templates select="key('kNamedSiblings', 
                                         concat(generate-id(..), '+', name())
                                        )/node()" />
      </xsl:copy>
  </xsl:template>

  <xsl:template match="*[not(*) and . = '']" />
  <xsl:template match="*[generate-id() != 
                         generate-id(key('kNamedSiblings', 
                                         concat(generate-id(..), '+', name()))[1]
                                    )]" />
</xsl:stylesheet>

在您的示例输入上运行时,结果是:

<tns:Grand_Parent_XML xmlns:tns="...">
  <GrandParent>
    <Parent>
      <Child>
        <Age>3</Age>
        <Gender>Male</Gender>
        <Name>Todd</Name>
      </Child>
      <Other>1234</Other>
    </Parent>
  </GrandParent>
</tns:Grand_Parent_XML>

【讨论】:

    【解决方案2】:

    试试这个方法:

    <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="Parent">
        <xsl:copy>
            <Child>
                <xsl:apply-templates select="Child/*"/>
            </Child>
            <xsl:apply-templates select="*[not(self::Child)]"/>
        </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>
    

    或者,如果您愿意:

    <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="Parent">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <Child>
                <xsl:apply-templates select="Child/*"/>
            </Child>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="Child"/>
    
    </xsl:stylesheet>
    

    【讨论】:

      猜你喜欢
      • 2019-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多