Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.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
Xml 如何计算XSLT中的不同子字符串?_Xml_Xslt - Fatal编程技术网

Xml 如何计算XSLT中的不同子字符串?

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&

我有以下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>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(), '&#xa;')"/>
      </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 &apos;"), "&apos;")' />
        <xsl:variable name="quotedItem" select='concat("item &apos;", $item, "&apos;")' />
        <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>&#13;&#10;</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 "),"&apos;",""),
        "&#xA;")'/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>