首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XSLT2.0分裂电流组(),第一次出现元素

XSLT2.0分裂电流组(),第一次出现元素
EN

Stack Overflow用户
提问于 2020-08-31 18:28:56
回答 1查看 568关注 0票数 0

使用XSLT2.0,假设current-group() ={ A、X、B、B、X},其中A、B和X是元素。在B的第一次出现时,如何将有效且易读的方法拆分成两个序列S1和S2,使S1 ={ A,X}和S2 ={ B,B,X }?是否可以使用xsl:for-每个组构造来完成这一任务?

编辑:current-group()的元素不能保证是兄弟,但保证按文档顺序排列。

第一次尝试:使用xsl:for-每个组和组开始

代码语言:javascript
复制
<xsl:for-each-group select="current-group()" group-starting-with="B[1]">
  <xsl:choose>
    <xsl:when test="position() = 1">
      <!-- S1 := current-group() -->
    </xsl:when>
    <xsl:otherwise>
      <!-- S2 := current-group() -->
    </xsl:otherwise>
  </xsl:choose>
</xsl:for-each-group>

如果不存在当前组()的第一个B的前面的同级B,则这是可行的。我认为位置谓词[1]的作用域将是select子句,因为current-group()[self::B][1]返回正确的B。我很想知道为什么它没有这样的范围。

XML

代码语言:javascript
复制
<root>
  <A>A1</A>
  <B>B1-1</B>
  <B>B1-2</B>
  <A>A2</A>
  <B>B2-1</B>
  <B>B2-2</B>
</root>

XSLT

代码语言:javascript
复制
<xsl:template match="root">
  <xsl:copy>
    <xsl:for-each-group select="*" group-starting-with="A">
      <xsl:for-each-group select="current-group()" group-starting-with="B[1]">
        <xsl:choose>
          <xsl:when test="position() = 1">
            <S1><xsl:copy-of select="current-group()" /></S1>
          </xsl:when>
          <xsl:otherwise>
            <S2><xsl:copy-of select="current-group()" /></S2>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

结果

代码语言:javascript
复制
<root>
  <S1>
    <A>A1</A>
  </S1>
  <S2>
    <B>B1-1</B>
    <B>B1-2</B>
  </S2>
  <S1>
    <A>A2</A>
    <B>B2-1</B>
    <B>B2-2</B>
  </S1>
</root>

正如您所看到的,第一个组是正确的拆分,但第二个组不是。但是,如果将当前的group()包装在父类中,然后将其传递给select子句,这将有效,但这似乎效率低下。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-31 19:06:09

functx库定义了一个函数functx:index-of-node (index-of-node.html):

代码语言:javascript
复制
<xsl:function name="functx:index-of-node" as="xs:integer*"
              xmlns:functx="http://www.functx.com">
  <xsl:param name="nodes" as="node()*"/>
  <xsl:param name="nodeToFind" as="node()"/>

  <xsl:sequence select="
  for $seq in (1 to count($nodes))
  return $seq[$nodes[$seq] is $nodeToFind]
 "/>

</xsl:function>

这将减少你的第二种方法

代码语言:javascript
复制
<xsl:template match="root">
  <xsl:copy>
    <xsl:for-each-group select="*" group-starting-with="A">
        <xsl:variable name="pos" select="functx:index-of-node(current-group(), (current-group()[self::B])[1])"/>
        <S1>
            <xsl:copy-of select="current-group()[position() lt $pos]"/>
        </S1>
        <S2>
            <xsl:copy-of select="current-group()[position() ge $pos]"/>
        </S2>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

在带有扩展函数saxon:items-beforesaxon:items-from匿名函数的语法扩展的Saxon10PE或EE的“新"XSLT 4”世界中,您可以将其编写为

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saxon="http://saxon.sf.net/"
    exclude-result-prefixes="#all" version="3.0">

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:output indent="yes"/>

    <xsl:template match="root">
        <xsl:copy>
            <xsl:for-each-group select="*" group-starting-with="A">
                <S1>
                    <xsl:apply-templates
                        select="saxon:items-before(current-group(), .{ . instance of element(B) })"/>
                </S1>
                <S2>
                    <xsl:apply-templates
                        select="saxon:items-from(current-group(), .{ . instance of element(B) })"/>
                </S2>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63676278

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档