在XSLT中的两个特定节点之间应用模板

时间:2012-07-23 18:25:41

标签: xslt xpath xslt-2.0

我在xsl:for-each-group中遇到了一个问题,它在here中得到了很好的解决。现在我还有其他一些问题。我喜欢这个作为输入。

<?xml version="1.0" encoding="UTF-8"?>

    <body>
       <p name ="section">this is section</p>
       <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 ="section">this is section</p>
       <p name="h1-title " other="other-h1">XSLT and XQuery</p>
       <p name="h2-title " other=" other-h2">XSLT</p>
       <p name ="section">this is section</section>
       <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>
   <section>
   <p name ="section">this is section</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 XMLdatabases    
         </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>
</section>
<section>
<p name ="section">this is section</p>
<h1>
            <p name="h1-title " other="other-h1">XSLT and XQuery</p>
       <h2>   
            <p name="h2"-title other=" other-h2">XSLT</p>
       </h2>
</h1>
</section>
<section>
<p name ="section">this is section</p>
<h1>
            <p name="h1-title " other="other-h1">XSLT and XQuery</p>
       <h2>   
            <p name="h2"-title other=" other-h2">XSLT</p>
       </h2>
</h1>
</section>
</body>

我用过的样式表(工作不正常)

    <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" name ="myTemplate">
      <xsl:copy>
        <xsl:sequence select="mf:group(*, 1)"/>
      </xsl:copy>
    </xsl:template>

   <xsl:template match="body[@name='section']">
        <section>
            <xsl:call-template name="myTemplate"/>
        </section>
    </xsl:template>    
    </xsl:stylesheet>

但这不正确。像<p name ="section">this is section</p>这样的东西似乎很广泛。不仅如此,还有很少人喜欢这样。如果有人请告诉我如何处理section我也可以为其他人做这件事。请告诉我如何正确地做到这一点。

ADDED

<body>
<intro>
<p></p>
<p></p>
</intro>

<section>
<para>
</para>
<h1></h2>
<h2></h2>
</section>

<section>
<para>
</para>
<h1></h2>
<h2></h2>
</section>

<sumary>
</summary>
</body>

我做了什么

<xsl:for-each-group select="*" group-starting-with="p[@name = 'intro']">
            <intro>
                    <xsl:apply-templates select="current()"/>
            </intro>
</xsl:for-each-group>

1 个答案:

答案 0 :(得分:2)

我认为你主要想要另一个分组步骤;样式表

<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:for-each-group select="*" group-starting-with="p[@name = 'section']">
      <section>
        <xsl:sequence select="mf:group(current-group(), 1)"/>
      </section>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

转换更正后的输入

<?xml version="1.0" encoding="UTF-8"?>

    <body>
       <p name ="section">this is section</p>
       <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 ="section">this is section</p>
       <p name="h1-title" other="other-h1">XSLT and XQuery</p>
       <p name="h2-title" other=" other-h2">XSLT</p>
       <p name ="section">this is section</p>
       <p name="h1-title" other="other-h1">XSLT and XQuery</p>
       <p name="h2-title" other=" other-h2">XSLT</p>
    </body>

进入结果

<body>
   <section>
      <p name="section">this is section</p>
      <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>
   </section>
   <section>
      <p name="section">this is section</p>
      <h1>
         <p name="h1-title" other="other-h1">XSLT and XQuery</p>
         <h2>
            <p name="h2-title" other=" other-h2">XSLT</p>
         </h2>
      </h1>
   </section>
   <section>
      <p name="section">this is section</p>
      <h1>
         <p name="h1-title" other="other-h1">XSLT and XQuery</p>
         <h2>
            <p name="h2-title" other=" other-h2">XSLT</p>
         </h2>
      </h1>
   </section>
</body>

我认为这有你发布的结构,除了<p name="h-title" other="main">Introduction</p>元素在一个部分内,而你发布的例子将它移到顶部。我不确定这样做的规则是什么,所以我没有尝试实现它。请澄清您是否只是想将该单个元素移到顶部而不是对其应用分组,或者是否有更复杂的规则来豁免某些元素。

[edit]如果你只是想将所有p[@name = 't-title']移到顶部而不是将它们分组,那么以上样式表的以下改编应该可以完成这项任务:

<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:apply-templates select="p[@name = 'h-title']"/>
    <xsl:for-each-group select="* except p[@name = 'h-title']" group-starting-with="p[@name = 'section']">
      <section>
        <xsl:sequence select="mf:group(current-group(), 1)"/>
      </section>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>