2011-03-23 39 views
1

在XSLT 1.0,在論壇中一個常見的問題是如何平HTML轉換成XML層次,其中許多次<p>標籤歸結爲嵌套文本<br />標記之間。分組在XSLT 2.0類似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> 
+0

這將是一個更容易破譯你」重新詢問你是否包含了一些樣本輸入和輸出XML。 – 2011-03-24 02:34:06

+0

該規則加上一個身份規則將產生確切的輸出。問題是什麼? – 2011-03-27 16:49:19

+0

好問題,+1。查看我的答案,獲得完整,簡短和簡單的解決方案。 :) – 2011-03-27 18:37:52

回答

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

我的示例對於該問題太簡單了。頁面開始標記可能出現在深度嵌套div之類的東西的末尾,真正需要關閉所有打開的標記,然後重新打開以啓動頁面來包裝內容。但它不再是一個問題,因爲我能夠獲得不同的源XML,不允許頁面在任意位置啓動。謝謝你的幫助! – Mattio 2011-03-29 21:24:55

+0

@Mattio:不客氣。 – 2011-03-29 22:25:17