使用for-each-group实现高性能XSLT

Set*_*ger 3 xslt xpath xslt-2.0

我有一个XSLT(1.0)样式表.它没有问题.我想把它变成2.0.我想使用xsl:for-each-group(并使其具有高性能).有可能的?怎么样?请解释.

我有很多地方喜欢

    <xsl:if test="test condition">
     <xsl:for-each select="wo:tent">
     <width aidwidth='{/wo:document/styles [@wo:name=current()/@wo:style-name]/@wo:width}'
</xsl:for-each>
    </xsl:if>
Run Code Online (Sandbox Code Playgroud)

添加

<xsl:template match="wo:country">
            <xsl:for-each select="@*">
                <xsl:copy/>
            </xsl:for-each>
            <xsl:variable name="states" select="wo:pages[@xil:style = &quot;topstates&quot; or @xil:style = &quot;toppage-title&quot;]"/>
            <xsl:variable name="provinces" select="wo:pages[@xil:style = &quot;topprovinces&quot;]"/>
            <xsl:choose>
                <xsl:when test="$states">
                    <xsl:apply-templates select="$states[2]/preceding-sibling::*"/>
                    <xsl:apply-templates select="$states[2]" mode="states">
                        <xsl:with-param name="states" select="$states[position() != 0]"/>
                    </xsl:apply-templates>
                </xsl:when>
                <xsl:when test="$provinces">
                    <xsl:apply-templates select="$provinces[2]/preceding-sibling::*"/>
                    <xsl:apply-templates select="$provinces[2]" mode="provinces">
                        <xsl:with-param name="provinces" select="$provinces[position() != 2]"/>
                    </xsl:apply-templates>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates/>
                </xsl:otherwise>
            </xsl:choose>
    </xsl:template>
Run Code Online (Sandbox Code Playgroud)

来源

<?xml version="1.0" encoding="UTF-8"?>
<wo:country>
   some stuff
</wo:country>
Run Code Online (Sandbox Code Playgroud)

Sea*_*kin 7

我假设你想要深入描述xsl:for-each-group以及如何使用它.如果这不是您要求的,请告诉我.

XSLT 2.0中的新指令采用一组项目并对它们进行分组.这组项目称为"人口",这些组只是被称为组.该指令依次处理每个组.

xsl:for-each-group指令的可能属性包括:

  1. 选择
  2. 通过...分组
  3. 组相邻的
  4. 基团的起始-与
  5. 小组收官,与
  6. 整理

@select是强制性的.其他是可选的.它可以使用任意数量的xsl:sort子(但它们必须先出现),然后是序列构造函数."序列构建器"是进入模板等内部的所有序列发射类型指令的术语.

@选择

select属性指定XPATH表达式,该表达式计算要分组的总体.

@通过...分组

group-by属性指定XPATH表达式,当分组类型为公共值时,可以使用该表达式.群体中评估为相同分组值的每个项目与另一个项目位于同一组中.

当分组类型按公共值分组时,XSLT 1.0 Muenchian分组并不太难.有两种更常见的分组形式:按相似值对相邻项目进行分组; 并对一组相邻的项目进行分组,这些项目的组在结束时或在开始时通过某种测试划分.虽然这两种形式的分组仍然可以与Muenchian一起使用,但它变得相对复杂.关于这些类型的Muenchian也会在规模上效率较低,因为使用了兄弟轴(不过你拼写了!).

想到XSLT 2.0的另一个优点是Muenchian只适用于节点集,而xsl:for-each-group在应用程序中更广泛,因为它适用于一系列项目,而不仅仅是节点.

@ group-by表达式的结果将是一系列项目.该序列被雾化和去除.正在测试的人口项目将是每个值的一个组的成员.这是一个奇怪的结果,使用@ group-by,item可能是多个组的成员,甚至可能不是.虽然我怀疑你可以在XSLT 2.0中做的任何事情,你可以通过一些曲折的路径,在XSLT 1.0中,将项目分成两组的能力在XSLT 1.0 Muenchian中可以很安静.

@组相邻的

group-by,group-adjacent,group-starting-with和group-ending-with属性是互斥的,因为它们指定了不同类型的分组.具有公共值且在群体中相邻的项目被组合在一起.与@ group-by不同,@ group-adjacent必须在雾化后评估单个原子值.

基团的起始-与

与select,group-adjacent和group-by不同,此属性不指定XPATH选择表达式,而是指定模式,与xsl:template/@ match指定模式而非选择的方式相同.如果人口中的项目通过模式测试或者是人口中的第一个项目,那么它将启动一个新组.否则,该项目将继续前一项目中的组.

Martin提到了规范示例(w3.org/TR/xslt20/#grouping-example).从该参考文献中,我将复制标题为"通过其初始元素识别组"的示例,但稍微改变它以强调关于人口的初始项目的观点.

所以这是我们的输入文档(从w3规范中复制.包含孤立行是我的)...

<body>
  <p>This is an orphaned paragraph.</p>
  <h2>Introduction</h2>
  <p>XSLT is used to write stylesheets.</p>
  <p>XQuery is used to query XML databases.</p>
  <h2>What is a stylesheet?</h2>
  <p>A stylesheet is an XML document used to define a transformation.</p>
  <p>Stylesheets may be written in XSLT.</p>
  <p>XSLT 2.0 introduces new grouping constructs.</p>
</body>
Run Code Online (Sandbox Code Playgroud)

...我们想要做的是将组定义为以h2开头的节点,并包括以下所有p直到下一个h2.w3给出的示例解决方案是使用@ group-starting-with ...

<xsl:template match="body">
  <chapter>
        <xsl:for-each-group select="*" group-starting-with="h2"      >
          <section title="{self::h2}">
            <xsl:for-each select="current-group()[self::p]">
              <para><xsl:value-of select="."/></para>
            </xsl:for-each> 
          </section>
        </xsl:for-each-group>
  </chapter>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

在规范示例中,当输入不包含孤立行时,这会产生所需的结果......

<chapter>
  <section title="Introduction">
    <para>XSLT is used to write stylesheets.</para>
    <para>XQuery is used to query XML databases.</para>
  </section> 
  <section title="What is a stylesheet?">
    <para>A stylesheet is an XML document used to define a transformation.</para>
    <para>Stylesheets may be written in XSLT.</para>
    <para>XSLT 2.0 introduces new grouping constructs.</para>
  </section>
</chapter>
Run Code Online (Sandbox Code Playgroud)

虽然在我们的特定情况下,我们得到了......

<chapter>
   <section title="">
      <para>This is an orphaned paragraph.</para>
   </section>
   <section title="Introduction">
      <para>XSLT is used to write stylesheets.</para>
      <para>XQuery is used to query XML databases.</para>
   </section>
   <section title="What is a stylesheet?">
      <para>A stylesheet is an XML document used to define a transformation.</para>
      <para>Stylesheets may be written in XSLT.</para>
      <para>XSLT 2.0 introduces new grouping constructs.</para>
   </section>
</chapter>
Run Code Online (Sandbox Code Playgroud)

如果不希望孤立线的初始部分,则有简单的解决方案.我现在不会进入他们.我的观点只是强调这样一个事实,即@ group-starting-with产生的第一组可以是一个'孤儿'组."孤儿"是指头部节点不符合指定模式的组.

@collat​​ion

collat​​ion属性指定排序规则URI,并标识用于比较字符串是否相等的排序规则.

电流 - 基团()

在xsl:for-each-group中,current-group()函数将当前正在处理的组作为一系列项返回.

电流分组键()

在xsl:for-each-group中,current-group()函数返回当前组密钥.我不确定,但我相信这只能是一种原子类型.也不确定,但我相信这个功能仅适用于@ group-by和@ group-adjacent类型的分组.

@ group-by与@ group-adjacent

在某些情况下,您可以在具有相同功能结果的这两种排序类型之间进行选择.在这种情况下,@ group-adjacent优先于@ group-by,因为它可能更有效地处理.

模式与选择

某些XSLT 2.0指令属性包含选择表达式.迈克尔凯称这些"XPath表达".就个人而言,当与模式并列时,我觉得更好的描述将是"选择表达".其他属性包含模式或"匹配表达式".虽然这两个都包含相同的语法,但它们是非常不同的野兽.两者之间的相似性经常使XSLT初学者认为xsl:template/@匹配不是作为模式,而是作为选择表达式.结果是初学者对模板序列构造函数中position()函数的值有很多困惑.如前所述,在xsl:for-each-group中,@ select,@ group-by和@ group-adjacent是select表达式,但@ group-starting-with和@ group-ending-with是模式.所以这是区别:

  1. 选择表达式就像一个函数.输入是上下文文档,上下文序列,上下文项,上下文位置,当然还有实际表达式.输出是一系列项目.根据实际使用的位置,这可能成为下一个上下文序列.默认轴是child ::.
  2. 与select表达式不同,模式的默认轴是self ::.模式也像一个函数.它的输入和以前一样,它的输出不是序列,而是布尔值.正在测试某个项目以查看它是否与模式匹配.正在测试的项目是上下文项目.临时评估匹配表达式,因为它是一个选择表达式.然后测试返回的序列以查看上下文项是否是成员.然后丢弃返回的序列.如果是成员,则结果为true或'match',否则为false.