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

问题描述:

我在xsl:for-each-group中遇到了问题,它在here中很好地解决了。现在我还有其他一些问题。我有这样的输入。现在在XSLT中的两个特定节点之间应用模板

<?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> 
+0

Setinger:我真的不明白转型应该是这样做的。请编辑问题并解释。大概一个非常小的例子就足够了 - 而且这个要求只应该是你无法实现的要求 - 请跳过所有其他要求。一个简单的示例XML文档可能只有10行。 – 2012-07-24 02:51:32

+0

@Dimitre,我用简单的关卡增加了更多的问题。请看看。 – Setinger 2012-07-26 05:32:33

+0

Setinger,你已经添加了一个示例,请解释一下是什么,是你有可能的输入还是你想要的输出?如果它是一个可能的输入,你也需要显示你想要的输出。 – 2012-07-26 09:41:26

我想你主要是想另一个划分步骤;样式表

<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>元素是一节中的例外而您发布的示例将其移至顶端。我不确定这样做的规则是什么,所以我没有试图实现这一点。请说明您是否只想将该单一元素移到顶部,而不是将该组应用到该元素,或者是否有更复杂的规则来豁免某些元素。

[编辑]如果你只是想将所有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> 
+0

非常感谢Martin。这真的很棒。这与我给出的例子非常吻合。但就像我告诉你,当我有更多的水平,这是困难的。我在问题中添加了示例级别以及我试图使其工作的内容。但它不正确。你能告诉我该怎么做吗? – Setinger 2012-07-26 05:26:48

+0

如果我在这里感到困惑,请看我的新问题。 – Setinger 2012-07-27 18:18:04