Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.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
使用XLST对XML中的类似节点进行分组_Xml_Xslt - Fatal编程技术网

使用XLST对XML中的类似节点进行分组

使用XLST对XML中的类似节点进行分组,xml,xslt,Xml,Xslt,我找到了一个问题,但找不到解决问题的方法 我有一个XML,如下所示 <name> <text class="002. AB vs BC"> Sample</text> <text class="003. DC vs BC"> Sample</text> <text class="004. CD vs BC"> Sample</text> <text class="005

我找到了一个问题,但找不到解决问题的方法

我有一个XML,如下所示

<name>
    <text class="002. AB vs BC">  Sample</text>
    <text class="003. DC vs BC">  Sample</text>
    <text class="004. CD vs BC">  Sample</text>
    <text class="005. AB vs BC">  Sample</text>
    <text class="006. AB vs BC">  Sample</text>
    <text class="007. EF vs BC">  Sample</text>
    <text class="008. CD vs BC">  Sample</text>
    <text class="009. DC vs BC">  Sample</text>
    <text class="010. AB vs BC">  Sample</text>
    <text class="011. EF vs BC">  Sample</text>
    <text class="012. AB vs BC">  Sample</text>

</name>
<name>
    <group name="AB">
        <text class="002. AB vs BC">  Sample</text>
        <text class="005. AB vs BC">  Sample</text>
        <text class="006. AB vs BC">  Sample</text>
        <text class="010. AB vs BC">  Sample</text>
        <text class="012. AB vs BC">  Sample</text>
    </group>
    <group name="EF">
        <text class="007. EF vs BC">  Sample</text>
        <text class="011. EF vs BC">  Sample</text>
    </group>
    <group name="CD">
        <text class="008. CD vs BC">  Sample</text>
        <text class="004. CD vs BC">  Sample</text>
    </group>
    <group name="DC">
        <text class="003. DC vs BC">  Sample</text>
        <text class="009. DC vs BC">  Sample</text>
    </group>
</name>

样品
样品
样品
样品
样品
样品
样品
样品
样品
样品
样品
我需要对所有具有类似类中第一个单词属性的节点进行分组,如下所示

<name>
    <text class="002. AB vs BC">  Sample</text>
    <text class="003. DC vs BC">  Sample</text>
    <text class="004. CD vs BC">  Sample</text>
    <text class="005. AB vs BC">  Sample</text>
    <text class="006. AB vs BC">  Sample</text>
    <text class="007. EF vs BC">  Sample</text>
    <text class="008. CD vs BC">  Sample</text>
    <text class="009. DC vs BC">  Sample</text>
    <text class="010. AB vs BC">  Sample</text>
    <text class="011. EF vs BC">  Sample</text>
    <text class="012. AB vs BC">  Sample</text>

</name>
<name>
    <group name="AB">
        <text class="002. AB vs BC">  Sample</text>
        <text class="005. AB vs BC">  Sample</text>
        <text class="006. AB vs BC">  Sample</text>
        <text class="010. AB vs BC">  Sample</text>
        <text class="012. AB vs BC">  Sample</text>
    </group>
    <group name="EF">
        <text class="007. EF vs BC">  Sample</text>
        <text class="011. EF vs BC">  Sample</text>
    </group>
    <group name="CD">
        <text class="008. CD vs BC">  Sample</text>
        <text class="004. CD vs BC">  Sample</text>
    </group>
    <group name="DC">
        <text class="003. DC vs BC">  Sample</text>
        <text class="009. DC vs BC">  Sample</text>
    </group>
</name>

样品
样品
样品
样品
样品
样品
样品
样品
样品
样品
样品

如何实现这一点?

这是一个非常简单的分组问题

如果仅限于XSLT1.0,则需要使用

如果您使用的是XSLT2.0+,那么可以使用

例子

XSLT1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="class" match="text" 
    use="substring-before(substring-after(normalize-space(@class), ' '),' ')"/>

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

  <xsl:template match="/name">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each select="text[count(.|key('class', substring-before(substring-after(normalize-space(@class), ' '),' '))[1])=1]">
        <xsl:variable name="key" select="substring-before(substring-after(normalize-space(@class), ' '),' ')"/>
        <group name="{$key}">
          <xsl:apply-templates select="key('class',$key)"/>
        </group>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
小提琴:


注意:输出的顺序与您的示例不同,但我没有看到任何排序逻辑。

使用XSLT-2.0,您可以对每个组使用
xsl:for-each-group
和以下模板:

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

  <xsl:template match="text()" />

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

  <xsl:template match="name">
    <xsl:copy>
        <xsl:for-each-group select="text" group-by="tokenize(@class,' ')[2]">
            <group name="{current-grouping-key()}">
                <xsl:for-each select="current-group()">
                    <xsl:copy-of select="." />
                </xsl:for-each>
            </group>
        </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

输出为:

<name>
   <group name="AB">
      <text class="002. AB vs BC">  Sample</text>
      <text class="005. AB vs BC">  Sample</text>
      <text class="006. AB vs BC">  Sample</text>
      <text class="010. AB vs BC">  Sample</text>
      <text class="012. AB vs BC">  Sample</text>
   </group>
   <group name="DC">
      <text class="003. DC vs BC">  Sample</text>
      <text class="009. DC vs BC">  Sample</text>
   </group>
   <group name="CD">
      <text class="004. CD vs BC">  Sample</text>
      <text class="008. CD vs BC">  Sample</text>
   </group>
   <group name="EF">
      <text class="007. EF vs BC">  Sample</text>
      <text class="011. EF vs BC">  Sample</text>
   </group>
</name>

样品
样品
样品
样品
样品
样品
样品
样品
样品
样品
样品

XSLT的哪个版本?如果为1.0,则需要使用。如果>1.0,您可以使用。我已经在上面的帖子中更新了XML代码。您能为我提供一个XSL 1.0解决方案吗?我想不出来out@Gangula-更新问题后,您将我的答案和另一个答案作废。我要把修订版退回去。这里有一个更新的提琴,试图处理新的需求:如果没有帮助,请创建一个新的问题。对不起,@Daniel,我已经更新了这个问题并等待了几天,但我认为因为它被标记为已解决,所以没有得到任何关注。谢谢你的更新。你能为我推荐一个学习XSL的资源吗。我想为我的其他几个XML文件编写一些类似的代码。@Gangula-Michael Kay的《XSLT 2.0和XPath 2.0》一书将是一个很好的资源,即使对于XSLT 1.0也是如此。我知道Dimitre Novatchev有一门关于Pluralsight的课程。我没用过,但迪米特里肯定知道他的东西。可以在的底部找到链接(以及G.Ken Holman的书的链接)