Xml 如何计算XSLT中的不同子字符串?
我有以下XML片段:Xml 如何计算XSLT中的不同子字符串?,xml,xslt,Xml,Xslt,我有以下XML片段: <wrapper> <item timestamp="19.10.2011 12:05"> <comment>Used for orderID '011187' with item 'xyz1'</comment> </item> <item timestamp="01.06.2012 16:25"> <comment&
<wrapper>
<item timestamp="19.10.2011 12:05">
<comment>Used for orderID '011187' with item 'xyz1'</comment>
</item>
<item timestamp="01.06.2012 16:25">
<comment>Used for orderID '011379' with item 'xyz2'</comment>
</item>
<item timestamp="06.06.2012 14:32">
<comment>Used for orderID '011382' with item 'xyz2'</comment>
</item>
</wrapper>
用于带有项目“xyz1”的订单ID“011187”
用于带有项目“xyz2”的订单ID“011379”
用于带有项目“xyz2”的订单ID“011382”
我想知道每个项目发生了多少次。
在这种情况下:-1 x xyz1
-2xxyz2 因此,您必须以某种方式循环所有的
,提取文本后面带有item…
的引号(')之间的字符串,然后计算该字符串在包装器元素中总共出现的次数
您将如何在XSLT中解决此问题?在XSLT 2.0中,这是可行的:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="wrapper">
<xsl:for-each-group select="item/comment"
group-by="replace(tokenize(., ' ')[last()], '[^a-zA-Z0-9]', '')">
<xsl:sort select="current-grouping-key()"/>
<xsl:value-of select="concat('- ', count(current-group()), ' x ', current-grouping-key(), '
')"/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
小提琴:对于XSLT2,您最好使用fafl的答案。如果您仍然坚持使用XSLT 1,那么以下方法将起作用:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" encoding="UTF-8" indent="yes" />
<xsl:template match="node()|@*">
<xsl:apply-templates select="node()|@*" />
</xsl:template>
<xsl:template match="comment">
<xsl:variable name="item" select='substring-before(substring-after(., "item '"), "'")' />
<xsl:variable name="quotedItem" select='concat("item '", $item, "'")' />
<xsl:if test='generate-id(.) = generate-id(//comment[contains(text(), $quotedItem)])'>
<xsl:value-of select='count(//comment[contains(text(), $quotedItem)])' />
<xsl:text> x </xsl:text>
<xsl:value-of select="$item" />
<xsl:text> </xsl:text>
</xsl:if>
</xsl:template>
</xsl:transform>
x
让我们把它分解一下。第一个模板非常简单地递归应用模板。第二个模板匹配所有
元素
首先提取项目名称,方法是在项目'
之后取子字符串,然后在该结果中取项目'
之前的子字符串。这假设项目名称始终以项目“名称”
的形式出现。如果没有,你需要调整这个。结果分配给变量项
。请注意,单引号的使用使得这有点棘手,因为双引号和单引号都是XML标记。因此,select
属性值被放在单引号之间,而不是标准的双引号,实际用作文本的单引号通过引用代码>
然后分配一个名为quotedItem
的变量,该变量基本上是字符串item'name'
(name是实际的item值),以便以后的工作更轻松一些。它避免在引号外匹配项目名称,或部分匹配(例如,如果一条注释包含项目“xy”
和另一条项目“xyz”
)。同样,这对输入进行了假设
然后,if
元素中的测试检查当前
的生成id是否与包含quotedItem
子字符串的最后一个
的生成id相同,以便仅对每个项的最后一次出现执行操作。在这种情况下,操作是对包含quotedItem
子字符串的所有
元素进行计数,并将其输出为count x item
,后跟回车符和换行符
核心部分是变量和生成的id
技巧。剩下的将取决于你打算如何处理结果
xsltransform链接:这里是另一个使用Muenchian分组的XSLT1.0选项(xsl:key
)
示例(因为其他人都在做;-):1.0还是2.0?这两者在字符串处理上有很大区别。“提取引号(')之间的字符串”哪一个?在给定的示例中,所有实例中都有两个。你需要提供一个更具体的规则。@michael.hor257k:我是指“with item…”之后的第二个引号,我在问题中添加了信息。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements= "*"/>
<xsl:key name="items" match="comment"
use="substring-after(normalize-space(),'with item ')"/>
<xsl:template match="/wrapper">
<xsl:for-each select="item/comment[count(.|key('items',
substring-after(normalize-space(),'with item '))[1])=1]">
<xsl:variable name="items" select="key('items',
substring-after(normalize-space(),'with item '))"/>
<xsl:value-of select='concat("- ",count($items)," x ",
translate(substring-after(normalize-space(),"with item "),"'",""),
"
")'/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>