2016-11-08 100 views
0

我比較兩個XML文件之後生成一個XML文件。它看起來這本添加節點,XSLT - 通過分析文本字符串

<doc> 
    <para><change flag="start"/><content>changed text</content><change flag="end"/> para text</para> <!--considerd as a change--> 
    <para><change flag="start"/><content>changed <t/>text</content><change flag="end"/> para text</para><!--considerd as a change--> 
    <para><change flag="start"/>​<content>(1)</content><change flag="end"/> para text</para><!--not considerd as a change--> 
    <para><change flag="start"/>​<content>i.</content><change flag="end"/> para text</para><!--not considerd as a change--> 
    <para><change flag="start"/>​<content>•</content><change flag="end"/> para text</para><!--not considerd as a change--> 
    <para><change flag="start"/><content>​ </content><change flag="end"/> para text</para><!--not considerd as a change--> 
    <para><change flag="start"/><content>(1) this is a <t/> numberd list</content><change flag="end"/> para text</para><!--considerd as a change--> 
    <para><change flag="start"/>​<content>• this is a <t/> bullet list</content><change flag="end"/>para text</para><!--considerd as a change--> 
</doc> 

這裏<change>元素顯示兩個文件的差異和變化的內容是顯示在<change flag="start"/>​<change flag="end"/>元素之間。

我的要求是將其轉換爲html。並且<change flag="start"/>​<change flag="end"/>之間的內容(與兩個xml文件的差異)應該用<CH>元素覆蓋。

<html> 
    <head></head> 
    <body> 
     <p><CH>changed text</CH>para text</p> 
     <p><CH>changed text</CH>para text</p> 
     <p>​<CH>(1)</CH>para text</p> 
     <p>​<CH>i.</CH>para text</p> 
     <p>​<CH>•</CH>para text</p> 
     <p><CH>​ </CH>para text</p> 
     <p><CH>(1) this is a numberd list</CH>para text</p> 
     <p>​<CH>• this is a bullet list</CH>para text</p> 
    </body> 
</html> 

但這裏的問題是<change flag="start"/>​<change flag="end"/>加子彈,列表編號和一些空格。 eventhout當比較xml文件的html表示時,這些變化不應被視爲更改。

所以我真正期待的HTML輸出,

<html> 
    <head></head> 
    <body> 
     <p><CH>changed text</CH> para text</p> 
     <p><CH>changed text</CH> para text</p> 
     <p>​(1) para text</p> 
     <p>​(a) para text</p> 
     <p>​• para text</p> 
     <p>​ para text</p> 
     <p><CH>(1) this is a numberd list</CH> para text</p> 
     <p>​<CH>• this is a bullet list</CH> para text</p> 
    </body> 
</html> 

我寫了下面的XSLT做這個任務,

<xsl:template match="doc"> 
     <html> 
      <head></head> 
      <body> 
       <xsl:apply-templates/> 
      </body> 
     </html> 
    </xsl:template> 


    <xsl:template match="para"> 
     <p> 
      <xsl:apply-templates/> 
     </p> 
    </xsl:template> 


    <xsl:template match="*[preceding-sibling::change[@flag='start'] and following-sibling::change[@flag = 'end']] 
     [matches(.,$list.mapping/map/@numerator-regex)]"> 
     <CH> 
      <xsl:apply-templates/> 
     </CH> 
    </xsl:template> 


<xsl:variable name="list.mapping" as="element()*"> 
    <map numerator-regex="^\(\d\)"/> 
    <map numerator-regex="^\(\d\d\)"/> 
    <map numerator-regex="^\d\)"/> 
    <map numerator-regex="^\d\."/> 
    <map numerator-regex="^\([A-Za-z]\.\)"/> 
    <map numerator-regex="^•"/> 
    <map numerator-regex="^*"/> 
</xsl:variable> 


    <xsl:template match="content"> 
     <xsl:apply-templates/> 
    </xsl:template> 

但如預期,這是現在的工作..任何一個可以建議我如何做到這一點,特別是如何消除爲以下情況添加標籤,

  • bullets(•)[bullet contains <change flag="start"/>​<change flag="end"/>]
  • 列表編號(1),(一)[列表號包含<change flag="start"/>​<change flag="end"/>之間]
  • 空格[空格包含<change flag="start"/>​
+0

有多複雜,可以在單個'para'元素中有多個'change'開始/結束元素?什麼是包裝或不包裝的確切標準,爲什麼有一個例子,在開始的時候被包裝而另一個未包裝呢?你能定義一個有限的,明確定義的正則表達式模式列表,它匹配要包裝的輸入嗎? –

+0

@MartinHonnen,是的,它可以在單個段落中有多個變更開始/結束元素。如果更改僅爲子彈(不是該子彈點內的任何文本),則不會將其視爲更改。我更新了問題中可能的正則表達式。 – sanjay

回答

0

首先之間<change flag="end"/>],我認爲你需要將您的list.mapping變量更改爲包含$符號。 '^'匹配文本的開頭,$匹配文本的結尾。這將停止^\(\d\)匹配(1) this is a numberd list

<xsl:variable name="list.mapping" as="element()*"> 
    <map numerator-regex="^\(\d\)$"/> 
    <map numerator-regex="^\(\d\d\)$"/> 
    <map numerator-regex="^\d\)$"/> 
    <map numerator-regex="^\d\.$"/> 
    <map numerator-regex="^\([A-Za-z]\.\)$"/> 
    <map numerator-regex="^•$"/> 
    <map numerator-regex="^\*$"/> 
</xsl:variable> 

因爲你使用as="element()*"。至於匹配,這意味着你應該做$list.mapping/@numerator-regex,而不是$list.mapping/map/@numerator-regex。你也應該檢查不匹配的東西。

你想要的是這種狀況...

[not($list.mapping/@numerator-regex[matches(current(), .)])] 

試試這個XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:template match="doc"> 
     <html> 
      <head></head> 
      <body> 
       <xsl:apply-templates/> 
      </body> 
     </html> 
    </xsl:template> 

    <xsl:template match="para"> 
     <p> 
      <xsl:apply-templates/> 
     </p> 
    </xsl:template> 

    <xsl:template match="*[preceding-sibling::change[@flag='start'] and following-sibling::change[@flag = 'end']] 
     [not($list.mapping/@numerator-regex[matches(current(), .)])]"> 
     <CH> 
      <xsl:apply-templates/> 
     </CH> 
    </xsl:template> 

<xsl:variable name="list.mapping" as="element()*"> 
    <map numerator-regex="^\(\d\)$"/> 
    <map numerator-regex="^\(\d\d\)$"/> 
    <map numerator-regex="^\d\)$"/> 
    <map numerator-regex="^\d\.$"/> 
    <map numerator-regex="^\([A-Za-z]\.\)$"/> 
    <map numerator-regex="^•$"/> 
    <map numerator-regex="^\*$"/> 
</xsl:variable> 
</xsl:stylesheet> 

這可能不是給了你所需要的準確輸出,作爲輸入XML可能有一些隱藏的Unicode那些字符會影響事物,但它可能會給你一個開始。