【问题标题】:Grouping elements based on sec value using xslt 2.0使用 xslt 2.0 根据 sec 值对元素进行分组
【发布时间】:2017-11-22 21:40:01
【问题描述】:

我有按顺序排列的元素。我需要根据 sec 值对元素进行分组。下面我提到了我的意见。

    <body>
    <title>first</title>
    <entry><sec>s 2</sec><p><text>some text 1</text></p></entry>
    <entry><sec>s 3</sec><p><text>some text 2</text></p></entry>
    <section>section title</section>
<entry><sec>Sh 1</sec><p><text>some text 3</text></p></entry>
    <entry><sec>Sh 1<sub>Pt 2</sub></sec><p><text>some text 4</text></p></entry>
    <entry><sec>Sh 1<sub>item 1</sub></sec><p><text>some text 5</text></p></entry>
    <entry><sec>s 8</sec><p><text>some text 2</text></p></entry>
    <entry><sec>s 9</sec><p><text>some text 2</text></p></entry>
    <entry><sec>Sh 2<sub>item 2</sub></sec><p><text>some text 10</text></p></entry>
    <entry><sec>Sh 2</sec><p><text>some text 20</text></p></entry>
    </body>

我期待下面的输出。

 <body>
<title>first</title>
    <entry><sec>s 2</sec><p><text>some text 1</text></p></entry>
    <entry><sec>s 3</sec><p><text>some text 2</text></p></entry>
<section>section title</section>
    <group>
    <entry><sec>Sh 1</sec><p><text>some text 3</text></p></entry>
    <entry><sec>Sh 1<sub>Pt 2</sub></sec><p><text>some text 4</text></p></entry>
    <entry><sec>Sh 1<sub>item 1</sub></sec><p><text>some text 5</text></p></entry>
    </group>
    <entry><sec>s 8</sec><p><text>some text 2</text></p></entry>
    <entry><sec>s 9</sec><p><text>some text 2</text></p></entry>
    <group>
    <entry><sec>Sh 2<sub>item 2</sub></sec><p><text>some text 10</text></p></entry>
    <entry><sec>Sh 2</sec><p><text>some text 20</text></p></entry>
    </group>
    </body>

请尝试帮助我。

【问题讨论】:

  • 查看任何xsl:for-each-group group-by 示例,例如在w3.org/TR/xslt20/#grouping-examples 的规范中,它应该很容易。
  • 我对分组不熟悉,但我试过了。我无法带来正确的输出。请帮助某人。
  • 花点时间阅读一个示例并尝试对其进行调整,如果您真的无法让它发挥作用,请向我们展示您的努力。
  • 以下是我尝试的方法 跨度>

标签: xml xslt


【解决方案1】:

你可以试试:

<xsl:template match="body">
    <body>
    <xsl:for-each-group select="entry" 
        group-adjacent="starts-with(sec, 'Sh ')">
        <xsl:choose>
            <xsl:when test="current-grouping-key()">
                <group>
                <xsl:copy-of select="current-group()"/>
                </group>
            </xsl:when>
            <xsl:otherwise>
                    <xsl:copy-of select="current-group()"/>
            </xsl:otherwise>  
        </xsl:choose>
    </xsl:for-each-group>
    </body>
</xsl:template>

输出

    <body>
    <entry><sec>s 2</sec><p><text>some text 1</text></p></entry>
    <entry><sec>s 3</sec><p><text>some text 2</text></p></entry>
    <group>
    <entry><sec>Sh 1</sec><p><text>some text 3</text></p></entry>
    <entry><sec>Sh 1<sub>Pt 2</sub></sec><p><text>some text 4</text></p></entry>
    <entry><sec>Sh 1<sub>item 1</sub></sec><p><text>some text 5</text></p></entry>
    </group>
    <entry><sec>s 8</sec><p><text>some text 2</text></p></entry>
    <entry><sec>s 9</sec><p><text>some text 2</text></p></entry>
    <group>
    <entry><sec>Sh 2<sub>item 2</sub></sec><p><text>some text 10</text></p></entry>
    <entry><sec>Sh 2</sec><p><text>some text 20</text></p></entry>
    </group>
</body>

【讨论】:

  • 感谢您的意见。但我需要一个改变。 sec 值可能会随着 s1、ss 5 的变化而变化。所有 sec 不以 Sh 开头。请尝试其他解决方案。
  • @Reegan,比提供分组规则。
  • 我将条件设为 group-adjacent="sec/text()[1]"。但是发生了空序列错误。请任何解决方案。
【解决方案2】:

如果您不想在组中只有一个项目的情况下包装项目,请使用

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">


    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

     <xsl:template match="body"> 
       <xsl:copy>
                  <xsl:for-each-group select="entry" group-by="sec/text()[1]"> 
                    <xsl:choose>
                        <xsl:when test="current-group()[2]">
                            <group>
                              <xsl:apply-templates select="current-group()"/>                                
                            </group>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="."/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each-group>
       </xsl:copy>

       </xsl:template>
</xsl:transform>

http://xsltransform.net/pNmBy2c

【讨论】:

  • 大部分情况下我发现它带来了我所期望的。但有一条规则是,如果 entry 后面或前面的其他元素没有出现在输出中。
  • 那么,输入的可变性如何?如果您知道entry 元素之前有一些元素,那么只需在xsl:for-each-group 之前放置一个&lt;xsl:copy-of select="* except entry"/&gt;
  • 对不起。我仍然没有得到所需的输出
  • 任何人请尝试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多