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

时间:2018-05-08 10:12:49

标签: 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]</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>

识别具有相同描述的所有菜单元素。

请注意,并非所有菜单节点都有卡路里元素,因此可以在生成的相应选项卡列中插入空文本值。

从上面的例子中,我尝试创建一个看起来像的tsv报告(按描述元素排序):

01\tTwo of our famous Belgian Waffles with plenty of real maple [syrup]\t650
01\tTwo of our famous Belgian Waffles with plenty of real maple [syrup]\t350
05\tTwo of our famous Belgian Waffles with plenty of real maple [syrup]\t250
02\tLight Belgian waffles covered with an assortment of fresh berries and whipped cream\t900
02\tLight Belgian waffles covered with an assortment of fresh berries and whipped cream\t100

我使用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>

1 个答案:

答案 0 :(得分:1)

您可以for-each-group使用group-by="description",然后可以使用value-of separator="&#9;"输出文字格式:

<?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>

https://xsltfiddle.liberty-development.net/3NzcBsV