的xsl:for-各组需要帮助(xsl:for-each-group help needed)

2019-06-26 11:20发布

我经历了XSLT分组的例子和使用的,每个组高性能XSLT 。 我有换各组的问题。

我的XML

<?xml version="1.0" encoding="UTF-8"?>
<body>
   <p name="h-title" other="main">Introduction</p>
   <p name="h1-title " other="other-h1">XSLT and XQuery</p>
   <p name="h2-title" other=" other-h2">XSLT</p>
   <p name="">
      <p1 name="bold"> XSLT is used to write stylesheets.</p1>
   </p>
   <p name="h2-title " name="other-h2">XQuery</p>
   <p name="">
      <p1 name="bold"> XQuery is used to query XML databases.</p1>
   </p>
   <p name="h3-title" name="other-h3">XQuery and stylesheets</p>
   <p name="">
      <p1 name="bold"> XQuery is used to query XML databases.</p1>
   </p>
   <p name="h1-title " other="other-h1">XSLT and XQuery</p>
   <p name="h2-title " other=" other-h2">XSLT</p>
</body>

我的通缉输出

<?xml version="1.0" encoding="UTF-8"?>
<body>
   <p name="h-title " other="main">Introduction</p>
   <h1>
      <p name="h1-title " other="other-h1"> XSLT and XQuery </p>
      <h2>
         <p name="h2-title " other="other-h2">XSLT</p>
         <p name="">
            <p1 name="bold">XSLT is used to write stylesheets.
            </p1>
         </p>
      </h2>
      <h2>
         <p name="h2-title " other="other-h2"> XQuery is used to query XML databases    
         </p>
         <p name="">
            <p name="bold"> XQuery is used to query XML databases.</p>
         </p>
         <h3>
            <p name="h3-title " name="other-h3">XQuery and stylesheets</p>
            <p name="">
         <p1 name="bold"> XQuery is used to query XML databases.</p1>
           </p>
        </h3>
      </h2>
</h1>

<h1>
            <p name="h1-title " other="other-h1">XSLT and XQuery</p>
       <h2>   
            <p name="h2"-title other=" other-h2">XSLT</p>
       </h2>
</h1>
</body>

我想这一点。 (不工作)

<xsl:template match="body">


        <body>
            <xsl:for-each-group select="*" group-starting-with="@h1-title"      >
                <h1>
                    <xsl:for-each select="current-group()[self:: h1-title]">
                        <xsl:value-of select="."/> 
                        </xsl:for-each> 
                </h1>
            </xsl:for-each-group>

            <xsl:for-each-group select="*" group-starting-with="@h2-title"      >
                <h2>
                    <xsl:for-each select="current-group()[self::h2-title/@h2-title]">
                        <xsl:value-of select="."/>
                    </xsl:for-each> 
                </h2>
            </xsl:for-each-group>

            <xsl:for-each-group select="*" group-starting-with="@h3-title"      >
                <h3>
                    <xsl:for-each select="current-group()[self::h2-title/@h3-title]">
                        <xsl:value-of select="."/>
                    </xsl:for-each> 
                </h3>
            </xsl:for-each-group>

        </body>

  </xsl:template>

会有人告诉我正确的方式来获得我想要的结果呢?

Answer 1:

这里是使用XSLT样式表2.0 for-each-group在一个递归函数(I更喜欢用XSLT 2.0命名模板):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs mf">

<xsl:param name="prefix" as="xs:string" select="'h'"/>
<xsl:param name="suffix" as="xs:string" select="'-title'"/>

<xsl:output method="html" version="4.0" indent="yes"/>

<xsl:function name="mf:group" as="node()*">
  <xsl:param name="items" as="node()*"/>
  <xsl:param name="level" as="xs:integer"/>
  <xsl:for-each-group select="$items" group-starting-with="p[@name = concat($prefix, $level, $suffix)]">
    <xsl:choose>
      <xsl:when test="not(self::p[@name = concat($prefix, $level, $suffix)])">
        <xsl:apply-templates select="current-group()"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="h{$level}">
          <xsl:apply-templates select="."/>
          <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each-group>
</xsl:function>

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

<xsl:template match="body">
  <xsl:copy>
    <xsl:sequence select="mf:group(*, 1)"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

当我申请的是样式与撒克逊9的输入

<body>
   <p name="h-title" other="main">Introduction</p>
   <p name="h1-title" other="other-h1">XSLT and XQuery</p>
   <p name="h2-title" other=" other-h2">XSLT</p>
   <p name="">
      <p1 name="bold"> XSLT is used to write stylesheets.</p1>
   </p>
   <p name="h2-title" other="other-h2">XQuery</p>
   <p name="">
      <p1 name="bold"> XQuery is used to query XML databases.</p1>
   </p>
   <p name="h3-title" other="other-h3">XQuery and stylesheets</p>
   <p name="">
      <p1 name="bold"> XQuery is used to query XML databases.</p1>
   </p>
   <p name="h1-title" other="other-h1">XSLT and XQuery</p>
   <p name="h2-title" other=" other-h2">XSLT</p>
</body>

我得到的结果

<body>
   <p name="h-title" other="main">Introduction</p>
   <h1>
      <p name="h1-title" other="other-h1">XSLT and XQuery</p>
      <h2>
         <p name="h2-title" other=" other-h2">XSLT</p>
         <p name="">

            <p1 name="bold"> XSLT is used to write stylesheets.</p1>

         </p>
      </h2>
      <h2>
         <p name="h2-title" other="other-h2">XQuery</p>
         <p name="">

            <p1 name="bold"> XQuery is used to query XML databases.</p1>

         </p>
         <h3>
            <p name="h3-title" other="other-h3">XQuery and stylesheets</p>
            <p name="">

               <p1 name="bold"> XQuery is used to query XML databases.</p1>

            </p>
         </h3>
      </h2>
   </h1>
   <h1>
      <p name="h1-title" other="other-h1">XSLT and XQuery</p>
      <h2>
         <p name="h2-title" other=" other-h2">XSLT</p>
      </h2>
   </h1>
</body>


Answer 2:

这种变换键和处理h1-titleh6-title

<xsl:stylesheet version="1.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="body">
       <xsl:apply-templates select="p[@name='h1-title']" />
     </xsl:template>

     <xsl:key name="next-headings" match="p[@name='h6-title']"
       use="generate-id(preceding-sibling::p
                         [ @name='h1-title'
                        or @name='h2-title'
                        or @name='h3-title'
                        or @name='h4-title'
                        or @name='h5-title'
                        ][1])" />
     <xsl:key name="next-headings" match="p[@name='h5-title']"
       use="generate-id(preceding-sibling::p
                         [ @name='h1-title'
                        or @name='h2-title'
                        or @name='h3-title'
                        or @name='h4-title'
                        ][1])" />
     <xsl:key name="next-headings" match="p[@name='h4-title']"
       use="generate-id(preceding-sibling::p
                         [ @name='h1-title'
                        or @name='h2-title'
                        or @name='h3-title'
                        ][1])" />
     <xsl:key name="next-headings" match="p[@name='h3-title']"
       use="generate-id(preceding-sibling::p
                         [  @name='h1-title'
                        or @name='h2-title'
                        ][1])" />
     <xsl:key name="next-headings" match="p[@name='h2-title']"
       use="generate-id(preceding-sibling::p
                         [@name='h1-title'][1])" />

     <xsl:key name="immediate-nodes" match=
     "node()[not(self::p)
           or
            not(contains('|h1-title|h2-title|h3-title|h4-title|h5-title|h6-title|',
                         concat('|',@name,'|')
                        )
                )]"
       use="generate-id(preceding-sibling::p
             [contains('|h1-title|h2-title|h3-title|h4-title|h5-title|h6-title|',
                       concat('|',@name,'|')
                       )
             ][1])" />

     <xsl:template match=
      "p[contains('|h1-title|h2-title|h3-title|h4-title|h5-title|h6-title|',
                  concat('|',@name,'|')
                  )]">
       <xsl:variable name="vLevel" select="substring(@name,2,1)" />
       <xsl:element name="h{$vLevel}">
          <xsl:copy-of select="."/>
          <xsl:apply-templates select="key('immediate-nodes', generate-id())" />
          <xsl:apply-templates select="key('next-headings', generate-id())" />
       </xsl:element>
     </xsl:template>

     <xsl:template match="/*/node()" priority="-20">
       <xsl:copy-of select="." />
     </xsl:template>
</xsl:stylesheet>

当该XML文档上施加 (校正为所提供的一个和全光照均匀值name属性):

<body>
        <p name="h1-title" other="main">Introduction</p>
        <p name="h2-title" other="other-h2">XSLT and XQuery</p>
        <p name="h3-title" other=" other-h3">XSLT</p>
        <p name="">
                <p1 name="bold"> XSLT is used to write stylesheets.</p1>
        </p>
        <p name="h2-title" other="other-h2">XQuery</p>
        <p name="">
                <p1 name="bold"> XQuery is used to query XML databases.</p1>
        </p>
        <p name="h3-title" other="other-h3">XQuery and stylesheets</p>
        <p name="">
                <p1 name="bold"> XQuery is used to query XML databases.</p1>
        </p>
        <p name="h1-title" other="other-h1">XSLT and XQuery</p>
        <p name="h2-title" other=" other-h2">XSLT</p>
</body>

在想,正确的结果产生

<h1>
   <p name="h1-title" other="main">Introduction</p>
   <h2>
      <p name="h2-title" other="other-h2">XSLT and XQuery</p>
      <h3>
         <p name="h3-title" other=" other-h3">XSLT</p>
         <p name="">
            <p1 name="bold"> XSLT is used to write stylesheets.</p1>
         </p>
      </h3>
   </h2>
   <h2>
      <p name="h2-title" other="other-h2">XQuery</p>
      <p name="">
         <p1 name="bold"> XQuery is used to query XML databases.</p1>
      </p>
      <h3>
         <p name="h3-title" other="other-h3">XQuery and stylesheets</p>
         <p name="">
            <p1 name="bold"> XQuery is used to query XML databases.</p1>
         </p>
      </h3>
   </h2>
</h1>
<h1>
   <p name="h1-title" other="other-h1">XSLT and XQuery</p>
   <h2>
      <p name="h2-title" other=" other-h2">XSLT</p>
   </h2>
</h1>

请注意

这种转变解决了产生层级的主要问题 。 如果需要的是顶层只需要一些简单的改变name属性的值为"h-title"

如果有更多的层级是必要的,这个只需要机械添加相应的or条款,按键的定义,并附加所有的管道分隔字符串name属性的值与相应的新的字符串。

在这里,我已经适应并重新使用的杰尼·坦尼森了一个类似的问题的解决方案。



Answer 3:

您的每个分组的步骤走的是原始的元素集合作为输入的,而你需要每个步骤由前面的分组步骤产生的团体合作。 还有很多其他的错误太多,例如H1-标题不是属性名称。

它需要是这样的:

<xsl:for-each-group select="*" group-starting-with="*[@name='h1-title']">
<h1>
  <xsl:choose>
    <xsl:when test="@name='h1-title'">
      <xsl:for-each-group select="current-group()" group-starting-with="*[name='h2-title']">
        <xsl:choose>
        <h2>
          ... similar logic for the next level ...
        </h2>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy-of select="current-group()"/>
    </xsl:otherwise>
  </xsl:choose>
</h1>
</xsl:for-each-group>

你可以在尽可能深,你根据你想要多少级处理想窝; 或者,如果你想处理一个不确定的数字,你可以把代码命名模板并进行递归调用来处理一个新的水平。 在最里面的级别,离开了xsl:choose和刚做xsl:copy-of select="current-group()

(我只注意到了尾随空格在“名称”属性。如果这些真的存在,则需要将它们包括在对比测试,或做normalize-space()摆脱他们的。)



文章来源: xsl:for-each-group help needed