1

在 XSLT 1.0 中,论坛中的一个常见问题是如何将平面 HTML 转换为分层 XML,这很多时候归结为在<br />标签中的<p>标签之间嵌套文本。

我有一个类似的问题,我认为我已经使用 XSLT 2.0 部分解决了这个问题,但这对我来说是一种新方法,我想获得第二个意见。

XHTML 源代码<span class="pageStart"></span>分散在各处。它们可以出现在几个不同的父节点中。我想将一个页面开始标记和下一个页面之间的所有节点包装在一个<page>节点中。我目前的解决方案是:

<xsl:template match="*[child::span[@class='pageStart']]">
  <xsl:copy>
    <xsl:copy-of select="@*" />
      <xsl:for-each-group select="node()" 
                          group-starting-with="span[@class='pageStart']">
        <page>
          <xsl:apply-templates select="current-group()"/>
        </page>
      </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

这至少有一个缺陷——标记的父节点<page>在我不想要它时将它作为子节点。在其他作品中,如果在其中<div>任何地方都有一个子页面标记,则除了我期望的位置之外,还会<page>创建一个节点作为直接子节点。<div>

我曾希望我可以简单地使模板规则成为<xsl:template match="span[@class='pageStart']">,但无论我尝试什么, current-group() 似乎都是空的。我尝试的常识方法是<xsl:for-each-group select="node()" group-starting-with="span[@class='pageStart']">.

有没有更简单的方法来解决我缺少的这个问题?

编辑

这是输入的示例:

<?xml version="1.0" encoding="UTF-8"?>
<html>
<head></head>
<body>
    <span class="pageStart"/>
    <p>...</p>
    <div>...</div>
    <img />
    <p></p>
    <span class="pageStart"/>
    <div>...</div>
    <span class="pageStart"/>
    <p>...</p>
    <div>
        <span class="pageStart"/>
        <p>...</p>
        <p>...</p>
        <span class="pageStart"/>
        <div>...</div>
        <img/>
    </div>
</body>
</html>

我假设最后两个嵌套页面使这个问题变得更加困难,所以我很高兴将它作为输出,或者接近的东西:

<?xml version="1.0" encoding="UTF-8"?>
<html>
<head></head>
<body>
    <page>
        <span class="pageStart"/>
        <p>...</p>
        <div>...</div>
        <img />
        <p></p>
    </page>
    <page>
        <span class="pageStart"/>
        <div>...</div>
    </page>
    <page>
        <span class="pageStart"/>
        <p>...</p>
        <div>
            <page>
                <span class="pageStart"/>
                <p>...</p>
                <p>...</p>
            </page>
            <page>
                <span class="pageStart"/>
                <div>...</div>
                <img/>
            </page>
        </div>
    </page>
</body>
</html>
4

1 回答 1

0

这种转变

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

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

 <xsl:template match="*[span/@class='pageStart']">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:for-each-group select="node()"
       group-starting-with="span[@class='pageStart']">
     <page>
      <xsl:apply-templates select="current-group()"/>
     </page>
   </xsl:for-each-group>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<html>
<head></head>
<body>
    <span class="pageStart"/>
    <p>...</p>
    <div>...</div>
    <img />
    <p></p>
    <span class="pageStart"/>
    <div>...</div>
    <span class="pageStart"/>
    <p>...</p>
    <div>
        <span class="pageStart"/>
        <p>...</p>
        <p>...</p>
        <span class="pageStart"/>
        <div>...</div>
        <img/>
    </div>
</body>
</html>

产生想要的正确结果:

<html>
   <head/>
   <body>
      <page>
         <span class="pageStart"/>
         <p>...</p>
         <div>...</div>
         <img/>
         <p/>
      </page>
      <page>
         <span class="pageStart"/>
         <div>...</div>
      </page>
      <page>
         <span class="pageStart"/>
         <p>...</p>
         <div>
            <page>
               <span class="pageStart"/>
               <p>...</p>
               <p>...</p>
            </page>
            <page>
               <span class="pageStart"/>
               <div>...</div>
               <img/>
            </page>
         </div>
      </page>
   </body>
</html>
于 2011-03-27T18:36:12.707 回答