XSLT样式表:将元素合并为一个

时间:2010-09-22 14:27:13

标签: xslt

什么是将转换的XSLT 2.0样式表

<paramList>
    <param name="y" out="true"/>
    <param name="y" in="true"/>
    <param name="z" out="true"/>
    <param name="x" in="true"/>
</paramList>

<paramList>
    <param name="x" in="true" />
    <param name="y" in="true" out="true"/>
    <param name="z" out="true"/>
</paramList>

在结果中,“in,only”参数位于“in&amp; out”参数之前,而“in&amp; out”参数又位于“out,only”参数之前。此外,两个“y”元素已合并为一个。

4 个答案:

答案 0 :(得分:0)

<?xml version="1.0" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/paramList">
  <xsl:copy>
    <xsl:for-each-group select="param" group-by="@name">
      <xsl:sort select="current-group()/@in" order="descending"/>
      <xsl:sort select="current-group()/@out"/>
      <param name="{current-grouping-key()}">
        <xsl:for-each select="current-group()/@*">
          <xsl:copy/>
        </xsl:for-each>
      </param>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

以防有人需要在XSLT 1中执行此操作:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

    <xsl:key name="paramsByName" match="param" use="@name"/>
    <xsl:template match="/paramList">
        <xsl:copy>
            <xsl:for-each select="param[count(. | key('paramsByName', @name)[1]) = 1]">
            <xsl:sort select="@name"/>
            <xsl:copy>
                <xsl:for-each select="key('paramsByName', @name)">
                <xsl:copy-of select="@*"/>
            </xsl:for-each>
            </xsl:copy>
        </xsl:for-each>
    </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

这使用Munchian grouping,因为XSLT 1没有分组构造。

修改

显然也可以只复制in和out属性,在这种情况下,以下样式表完成工作(也遵循Dimetre的建议:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

    <xsl:key name="paramsByName" match="param" use="@name"/>
    <xsl:template match="/paramList">
        <xsl:copy>
            <xsl:for-each select="param[count(. | key('paramsByName', @name)[1]) = 1]">
            <xsl:sort select="@name"/>
            <xsl:copy-of select="key('paramsByName', @name)/@*[local-name() = 'in' or local-name() = 'out']"/>
        </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

一个小改进:

在@ Nick-Jones和@Obalix的解决方案中,写的时间更短

<xsl:copy-of select="current-group()/@*"/>

<xsl:copy-of select="key('paramsByName', @name)/@*"/>

分别

<xsl:for-each select="current-group()/@*">   
  <xsl:copy/>   
</xsl:for-each>   

<xsl:for-each select="key('paramsByName', @name)">     
 <xsl:copy-of select="@*"/>     
</xsl:for-each>     

答案 3 :(得分:0)

如果输入文档中有多个paramList元素,Obalix的答案可能不起作用。如果文档描述的软件界面中有多个程序,每个程序都有paramList,我认为这可能会引起海报的兴趣。

以下是输入示例:

<root>
  <func name="one">
    <paramList>
      <param name="y" out="true"/>
      <param name="y" in="true"/>
      <param name="z" out="true"/>
      <param name="x" in="true"/>
    </paramList>
  </func>

  <func name="two">
    <paramList>
      <param name="z" in="true"/>
    </paramList>
  </func>
</root>

这是我提出的样式表,建立在Obalix的答案之上。诀窍是使用包含paramList元素ID的本地密钥ID。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="paramsByName" match="param" use="concat(generate-id(..), '/', @name)"/>
  <xsl:template match="paramList">
    <xsl:copy>
       <xsl:variable name="id" select="generate-id(.)"/>
       <xsl:for-each select="param[count(. | key('paramsByName', concat($id, '/', @name))[1]) = 1]">
         <xsl:copy>
           <xsl:copy-of select="key('paramsByName', concat($id, '/', @name))/@*"/>
         </xsl:copy>
       </xsl:for-each>
     </xsl:copy>
  </xsl:template>
</xsl:stylesheet>