Xslt 3.0 检查xml文件,并使用xslt-3生成关于重复元素的报告

Xslt 3.0 检查xml文件,并使用xslt-3生成关于重复元素的报告,xslt-3.0,Xslt 3.0,给定以下xml作为输入,我尝试使用xslt-3创建一个报告 <breakfast_menu> <food> <name>01</name> <price>$5.95</price> <description>Two of our famous Belgian Waffles with plenty of real maple [syrup]</desc

给定以下xml作为输入,我尝试使用xslt-3创建一个报告

<breakfast_menu>
    <food>
        <name>01</name>
        <price>$5.95</price>
        <description>Two of our famous Belgian Waffles with plenty of real maple [syrup]</description>
        <calories>650</calories>
    </food>
    <food>
        <name>01</name>
        <price>$7.95</price>
        <description>Two of our famous Belgian Waffles with plenty of real maple [syrup]</description>
        <calories>350</calories>
    </food>
    <food>
        <name>02</name>
        <price>$8.95</price>
        <description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
        <calories>900</calories>
    </food>
    <food>
        <name>03</name>
        <price>$4.50</price>
        <description>Thick slices made from our homemade sourdough bread</description>
    </food>
    <food>
        <name>04</name>
        <price>$6.95</price>
        <description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
        <calories>100</calories>
    </food>
    <food>
        <name>05</name>
        <price>$7.95</price>
        <description>Two of our famous Belgian Waffles with plenty of real maple [syrup]</description>
        <calories>250</calories>
    </food>
</breakfast_menu>
我使用xsl v2的试用版:

<xsl:stylesheet version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"

  exclude-result-prefixes="xs">

  <xsl:output indent="yes"/>

  <xsl:key name="ids" match="*[@description]" use="@description"/> 

  <xsl:template match="/">
    <duplicates>
      <xsl:apply-templates select="//*[@description]"/>
    </duplicates>
  </xsl:template>


  <xsl:template match="*[@description]">
    <xsl:if test="count(key('ids', @description)) &gt; 1">
      <duplicate 
        id="{@description}" 
        dup-count="{count(key('ids', @description))}" 
        node-xpath="{string-join((for $node in ancestor::* return concat($node/name(),'[', count($node/preceding-sibling::*[name() = $node/name()])+1, ']'),concat(name(),'[', count(preceding-sibling::*[name() = current()/name()]) + 1, ']')
   ),'/')}">

      </duplicate>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

您可以对每个组使用
分组依据=“说明”
,然后您可以使用分隔符=“ ;”的
值输出文本格式:





您想要的输出格式似乎是纯文本,但是XSLT创建了一个XML文档,其中包含一个
duplicates
根元素,然后是仅具有属性的
duplicate
子元素。当您说您使用XSLT 2并希望使用XSLT 3时,您并不是对每个组使用
来识别重复项,而是一个键。此外,您说您希望按
说明
对重复项进行排序,但在以
开头的项之前,有以
两个
开头的项。因此,你需要澄清你的要求。一个小的修改,怎么可能在报告中,比如在第一行,有一个数字表示多次找到的描述的数量?在上面的问题中,结果是3我不确定你提到的
3
与什么有关。如果要输出组中的项目,可以使用
count(current-group())
,就像我在
中所做的那样。如果这没有帮助,那么问一个新问题。不,我需要的只是一个数字,类似于找到的所有组,求和(count(current-group())-1)。该总和将输出每个描述出现多次的次数,因此在上述示例中,结果为3。请提出一个新问题,如果要计算或汇总所有组,需要先以某种方式存储分组结果,这当然是可能的,但不属于对这个问题的评论。你是对的,我的错误:
<xsl:stylesheet version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"

  exclude-result-prefixes="xs">

  <xsl:output indent="yes"/>

  <xsl:key name="ids" match="*[@description]" use="@description"/> 

  <xsl:template match="/">
    <duplicates>
      <xsl:apply-templates select="//*[@description]"/>
    </duplicates>
  </xsl:template>


  <xsl:template match="*[@description]">
    <xsl:if test="count(key('ids', @description)) &gt; 1">
      <duplicate 
        id="{@description}" 
        dup-count="{count(key('ids', @description))}" 
        node-xpath="{string-join((for $node in ancestor::* return concat($node/name(),'[', count($node/preceding-sibling::*[name() = $node/name()])+1, ']'),concat(name(),'[', count(preceding-sibling::*[name() = current()/name()]) + 1, ']')
   ),'/')}">

      </duplicate>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">


  <xsl:output method="text" />

  <xsl:template match="breakfast_menu">
      <xsl:for-each-group select="food" group-by="description">
          <xsl:sort select="current-grouping-key()"/>
          <xsl:if test="current-group()[2]">
              <xsl:apply-templates select="current-group()"/>
          </xsl:if>
      </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="food">
      <xsl:value-of select="name, description, string(calories)" separator="&#9;"/>
      <xsl:text>&#10;</xsl:text>
  </xsl:template>

</xsl:stylesheet>