使用 xslt 转换(删除和重命名)xml 文件标签

Transforming (removing and renaming) xml file tags using xslt

我刚开始学习xslt,对此我很陌生。这就是为什么我在多次重试后没有得到想要的输出后才来问这个问题。我有这个输入 xml :

<root>
<type>sometype</type>
<attribute name="1st" value="val1"/>
<attribute name="2nd" value="val2"/>
<attribute name="nth" value="valn"/>
  <attribute name="first">
    <tagvalue>
      <entryMap name="mapvalue1">
        <new>
          <type>TypeA</type>
          <attribute name="attr1" value="aaa" />
        </new>
      </entryMap>
    </tagvalue>
  </attribute>
  <attribute name="second">
    <tagvalue>
      <entryMap name="mapvalue2">
        <new>
          <type>TypeB</type>
          <attribute name="attr2" value="bbb" />
        </new>
      </entryMap>
    </tagvalue>
  </attribute>
  <attribute name="third">
    <tagvalue>
      <entryMap name="mapvalue3">
        <new>
          <type>TypeC</type>
          <attribute name="attr3" value="ccc" />
        </new>
      </entryMap>
    </tagvalue>
  </attribute>
</root>

需要转换成这个输出 xml :

<root>
<type>sometype</type>
<attribute name="1st" value="val1"/>
<attribute name="2nd" value="val2"/>
<attribute name="nth" value="valn"/>
  <attribute name="common">
    <tagvalue>
      <entryMap name="mapvalue1">
        <new>
          <type>TypeA</type>
          <attribute name="attr1" value="aaa" />
        </new>
      </entryMap>
    </tagvalue>
    <tagvalue>
      <entryMap name="mapvalue2">
        <new>
          <type>TypeB</type>
          <attribute name="attr2" value="bbb" />
        </new>
      </entryMap>
    </tagvalue>
    <tagvalue>
      <entryMap name="mapvalue3">
        <new>
          <type>TypeC</type>
          <attribute name="attr3" value="ccc" />
        </new>
      </entryMap>
    </tagvalue>
  </attribute>
</root>

也就是说,这个标签出现了 3 次:<attribute name="first"> <attribute name="second"> <attribute name="third">。我只需要在开头出现一次,并将名称值重命名为“common”,即 <attribute name="common">。 我尝试使用 <xsl:template match="@value"> 作为重命名逻辑,但我无法成功合并它。

我目前的 xslt 是这样的:

<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:param name="removeElementsNamed" select="'attribute'"/>

<!-- identity transform -->
<xsl:template match="@*|node()" name="identity">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="*">
  <xsl:if test="not(name() = $removeElementsNamed)">
   <xsl:call-template name="identity"/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

但我知道我在某处做错了。我尝试使用多个模板,但没有得到所需的输出。如果有人能帮我解决这个问题,我将不胜感激。谢谢!

这是可以做到的一种方法:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0">
  
  <xsl:output method="xml"/>
  
  <xsl:template match="attribute[1]">
    <xsl:copy>
      <xsl:attribute name="name">common</xsl:attribute>
      <xsl:apply-templates select="//attribute/tagvalue"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="attribute[position()>1]"/>

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

这是可以做到的一种方法:https://xsltfiddle.liberty-development.net/nbspVbv/2

你为什么不简单地做:

XSLT 1.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="*"/>

<xsl:template match="/root">
    <xsl:copy>
        <attribute name="common">
            <xsl:copy-of select="attribute/tagvalue"/>
        </attribute>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

已添加:

要复制“通用”组中未包含的其他元素,您可以这样做:

    <xsl:template match="/root">
        <xsl:copy>
            <xsl:copy-of select="type | attribute[not(@name='first' or @name='second' or @name='third')]"/>
            <attribute name="common">
                <xsl:copy-of select="attribute[@name='first' or @name='second' or @name='third']/tagvalue"/>
            </attribute>
        </xsl:copy>
    </xsl:template>

或者,更优雅一点(避免对同一事物进行两次测试):

<xsl:template match="/root">
    <xsl:variable name="common" select="attribute[@name='first' or @name='second' or @name='third']" />
    <xsl:copy>
        <xsl:copy-of select="*[count(.|$common) != count($common)]"/>
        <attribute name="common">
            <xsl:copy-of select="$common/tagvalue"/>
        </attribute>
    </xsl:copy>
</xsl:template>