3

我正在尝试在 XSLT 2.0 中使用 xsl:for-each 对元素进行分组。

这是我输入的说明:

<root>
     <chapter>
           <heading> heading text </heading>
           <title> title </title>
           <p> 1111 </p>
           <p> 2222 </p>
           <center> text </center>
           <p> 3333 </p>
           <title>  another title </title>
           <p> 4444 </p>
           <center> text </center>
           <p> 5555 </p>
     </chapter>
     <chapter>
          <heading> heading text </heading>
          <title>  another title </title>
          <p> 6666 </p>
          <p> 7777 </p>
          <title>  another title </title>
          <p> 8888 </p>
          <p> 9999 </p>
     </chapter>
<root>

我试图通过匹配每个<title>元素并将每个后续元素分组到下<title>一个元素来分组这个文档<section>。这是我希望输出的样子:

<root>
     <chapter>
          <heading> Heading text </heading>
          <section>
               <title>  title </title>
               <p> 1111 </p>
               <p> 2222 </p>
               <center> text </center>
               <p> 3333 </p>
          </section>
          <section>
               <title>  title </title>
               <p> 4444 </p>
               <center> text </center>
               <p> 5555 </p>
          </section>
          <section>
               <title>  title </title>
               <p> 6666 </p>
               <p> 7777 </p>
               <center> text </center>
               <p> 8888 </p>
               <p> 9999 </p>
          </section>
     <chapter>
<root>

我当前的模板不起作用:

<xsl:template match="chapter">
    <chapter>
      <xsl:for-each-group select="*" group-starting-with="title">
             <section>
                <xsl:copy-of select="current-group()" />
             </section>
      </xsl:for-each-group>
    </chapter>             
</xsl:template>

上面的样式表确实对我想要的部分进行了分组,但是由于某种原因它也将每个<heading>元素分组到它自己的部分中。<section>有什么建议么?

提前致谢。

4

3 回答 3

4

我会用...

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />  

<xsl:template match="/*">
  <root>
    <xsl:for-each-group select="chapter" group-by="heading">
      <chapter>
        <xsl:copy-of select="current-group()[1]/heading" />
        <xsl:for-each-group select="current-group()/(* except heading)"
                            group-starting-with="title">
          <section>
            <xsl:copy-of select="current-group()" />
          </section>
        </xsl:for-each-group>
      </chapter>
    </xsl:for-each-group>
  </root>
</xsl:template>

</xsl:stylesheet>
于 2012-10-01T15:48:48.020 回答
4

我通常在 for-each-group 的主体中使用 xsl:choose 来区分真正以 group-starting-with 元素开头的组与第一个“真实组”之前的“前导臀部”。如果您知道“领先的臀部”将仅包含一个标题元素,那么您已经获得了许多其他效果很好的解决方案。另一个更通用的解决方案(因为它不对臀部里的东西做任何假设),但沿着同样的思路,是:

<xsl:copy-of select="title[1]/preceding-sibling::*">
<xsl:for-each-group select="title[1]/(., following-sibling::*)">
  <section>
     <xsl:copy-of select="current-group()"/>
  </section>
</xsl:for-each-group>
于 2012-10-01T19:32:49.110 回答
3

你可能想要

<xsl:copy-of select="current-group()" />

而不是value-of. 对于标题,如果您知道每一章只有一个heading元素,那么您可以说

<xsl:template match="chapter">
      <xsl:copy-of select="heading" />
      <xsl:for-each-group select="*[not(self::heading)]" group-starting-with="title">
             <section>
                <xsl:copy-of select="current-group()" />
             </section>
      </xsl:for-each-group>             
</xsl:template>

即单独拉出标题,然后将其从要分组的元素集中排除。

于 2012-10-01T15:26:30.840 回答