检查 xml 文件,并使用 xslt-3 生成关于重复元素的报告
inspect an xml file, and generate a report on duplicate elements using xslt-3
给定以下 xml 作为输入,我尝试使用 xslt-3 创建报告
<breakfast_menu>
<food>
<name>01</name>
<price>.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>.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>.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>.50</price>
<description>Thick slices made from our homemade sourdough bread</description>
</food>
<food>
<name>04</name>
<price>.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>.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)) > 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>
您可以使用for-each-group
到group-by="description"
,然后您可以使用value-of separator="	"
输出文本格式:
<?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="	"/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
给定以下 xml 作为输入,我尝试使用 xslt-3 创建报告
<breakfast_menu>
<food>
<name>01</name>
<price>.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>.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>.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>.50</price>
<description>Thick slices made from our homemade sourdough bread</description>
</food>
<food>
<name>04</name>
<price>.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>.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)) > 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>
您可以使用for-each-group
到group-by="description"
,然后您可以使用value-of separator="	"
输出文本格式:
<?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="	"/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>