Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用XSLT枚举具有相同名称的节点_Xslt_Muenchian Grouping - Fatal编程技术网

使用XSLT枚举具有相同名称的节点

使用XSLT枚举具有相同名称的节点,xslt,muenchian-grouping,Xslt,Muenchian Grouping,我有很多XML文件,它们常常多次包含节点(每次包含不同的数据)。 例如: 达塔 数据库 数据中心 数据 达泰 达塔夫 达塔 所需的输出将是: <?xml version="1.0" encoding="UTF-8"?> <SomeName> <Node1> DataA </Node1> <Node2> DataB </Node2&

我有很多XML文件,它们常常多次包含节点(每次包含不同的数据)。 例如:


达塔
数据库
数据中心
数据
达泰
达塔夫
达塔
所需的输出将是:

  <?xml version="1.0" encoding="UTF-8"?>  
    <SomeName>  
      <Node1>
        DataA
     </Node1>  
     <Node2>
        DataB
     </Node2>  
      <Node3>
        DataC
     </Node3>  
      <AnotherNode1>
        DataD
     </AnotherNode1>
      <AnotherNode2>
        DataE
     </AnotherNode2>
      <AnotherNode3>
        DataF
     </AnotherNode3>
     <SingleNode>
        DataG
     </SingleNode>
   </SomeName>  

达塔
数据库
数据中心
数据
达泰
达塔夫
达塔
问题是,我没有一个包含所有重复节点名的列表,所以我需要XSLT遍历所有节点,只对存在多次的节点进行编号。可能吗

有没有人对如何做到这一点有好的想法


谢谢

您可以使用
count(前面的同级元素::*[name(.)=name(current())])
获取与上下文元素同名的前面同级元素的数量,并使用
创建与上下文元素同名的元素,并在其后面附加字母“n”。将这些事实结合起来应该可以让你达到你想要的效果。

这里有一个完整的解决方案建议使用Muenchian方法进行分组,而不是基于
计数(前面:*[someCondition])
进行分组,这是非常低效的--O(N^2)

此转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kElsByName"
  match="/*/*" use="name()"/>

 <xsl:template match="/*">
   <SomeName>
     <xsl:for-each select=
      "*[generate-id()
        =
         generate-id(key('kElsByName', name())[1])
        ]
      ">

        <xsl:variable name="vsameNamedNodes" select=
         "key('kElsByName', name())"/>

        <xsl:variable name="vNumSameNamedNodes" select=
         "count($vsameNamedNodes)"/>

        <xsl:for-each select="$vsameNamedNodes">

         <xsl:element name="{concat(name(),
                             substring(position(),
                                       1 div ($vNumSameNamedNodes > 1)
                                       )
                                    )
                             }">
           <xsl:copy-of select="node()"/>
         </xsl:element>
       </xsl:for-each>
     </xsl:for-each>
   </SomeName>
 </xsl:template>
</xsl:stylesheet>
    <SomeName>
      <Node>
        DataA
     </Node>
     <Node>
        DataB
     </Node>
      <Node>
        DataC
     </Node>
      <AnotherNode>
        DataD
     </AnotherNode>
      <AnotherNode>
        DataE
     </AnotherNode>
      <AnotherNode>
        DataF
     </AnotherNode>
     <SingleNode>
        DataG
     </SingleNode>
   </SomeName>
<SomeName>
    <Node1>
        DataA
    </Node1>
    <Node2>
        DataB
    </Node2>
    <Node3>
        DataC
    </Node3>
    <AnotherNode1>
        DataD
    </AnotherNode1>
    <AnotherNode2>
        DataE
    </AnotherNode2>
    <AnotherNode3>
        DataF
    </AnotherNode3>
    <SingleNode>
        DataG
    </SingleNode>
</SomeName>

应用于提供的XML文档时

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kElsByName"
  match="/*/*" use="name()"/>

 <xsl:template match="/*">
   <SomeName>
     <xsl:for-each select=
      "*[generate-id()
        =
         generate-id(key('kElsByName', name())[1])
        ]
      ">

        <xsl:variable name="vsameNamedNodes" select=
         "key('kElsByName', name())"/>

        <xsl:variable name="vNumSameNamedNodes" select=
         "count($vsameNamedNodes)"/>

        <xsl:for-each select="$vsameNamedNodes">

         <xsl:element name="{concat(name(),
                             substring(position(),
                                       1 div ($vNumSameNamedNodes > 1)
                                       )
                                    )
                             }">
           <xsl:copy-of select="node()"/>
         </xsl:element>
       </xsl:for-each>
     </xsl:for-each>
   </SomeName>
 </xsl:template>
</xsl:stylesheet>
    <SomeName>
      <Node>
        DataA
     </Node>
     <Node>
        DataB
     </Node>
      <Node>
        DataC
     </Node>
      <AnotherNode>
        DataD
     </AnotherNode>
      <AnotherNode>
        DataE
     </AnotherNode>
      <AnotherNode>
        DataF
     </AnotherNode>
     <SingleNode>
        DataG
     </SingleNode>
   </SomeName>
<SomeName>
    <Node1>
        DataA
    </Node1>
    <Node2>
        DataB
    </Node2>
    <Node3>
        DataC
    </Node3>
    <AnotherNode1>
        DataD
    </AnotherNode1>
    <AnotherNode2>
        DataE
    </AnotherNode2>
    <AnotherNode3>
        DataF
    </AnotherNode3>
    <SingleNode>
        DataG
    </SingleNode>
</SomeName>

达塔
数据库
数据中心
数据
达泰
达塔夫
达塔
产生想要的结果

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kElsByName"
  match="/*/*" use="name()"/>

 <xsl:template match="/*">
   <SomeName>
     <xsl:for-each select=
      "*[generate-id()
        =
         generate-id(key('kElsByName', name())[1])
        ]
      ">

        <xsl:variable name="vsameNamedNodes" select=
         "key('kElsByName', name())"/>

        <xsl:variable name="vNumSameNamedNodes" select=
         "count($vsameNamedNodes)"/>

        <xsl:for-each select="$vsameNamedNodes">

         <xsl:element name="{concat(name(),
                             substring(position(),
                                       1 div ($vNumSameNamedNodes > 1)
                                       )
                                    )
                             }">
           <xsl:copy-of select="node()"/>
         </xsl:element>
       </xsl:for-each>
     </xsl:for-each>
   </SomeName>
 </xsl:template>
</xsl:stylesheet>
    <SomeName>
      <Node>
        DataA
     </Node>
     <Node>
        DataB
     </Node>
      <Node>
        DataC
     </Node>
      <AnotherNode>
        DataD
     </AnotherNode>
      <AnotherNode>
        DataE
     </AnotherNode>
      <AnotherNode>
        DataF
     </AnotherNode>
     <SingleNode>
        DataG
     </SingleNode>
   </SomeName>
<SomeName>
    <Node1>
        DataA
    </Node1>
    <Node2>
        DataB
    </Node2>
    <Node3>
        DataC
    </Node3>
    <AnotherNode1>
        DataD
    </AnotherNode1>
    <AnotherNode2>
        DataE
    </AnotherNode2>
    <AnotherNode3>
        DataF
    </AnotherNode3>
    <SingleNode>
        DataG
    </SingleNode>
</SomeName>

达塔
数据库
数据中心
数据
达泰
达塔夫
达塔

使用
计数(前面的兄弟姐妹::*[something])
效率很低(O(N^2))。请参阅我的答案以获得更有效的解决方案。好问题(+1)。请参阅我的答案,以获得一个完整且更高效的解决方案。哇。这也很好,很快!非常感谢XSLT!我所做的更改是将method=“xml”放在标题中以获得xml输出,但在其他方面,您的解决方案是完美的。再次感谢!实际上,是否有可能将其更改为不重命名唯一节点?XSLT基本上没有重命名SingleNode吗?谢谢@格林纳:是的,但是在评论中写新的解决方案很不方便。我可以编辑我的答案以包含最后一个要求。@Grinner:我编辑了我的答案。该解决方案现在正好生成您想要的输出。