2009-04-28 37 views
0

我正在嘗試修復一些使用正則表達式的雙語xml文件來匹配已知的錯誤內容模式並替換正確的值。 xml文件中的大多數問題都可以被認爲是拼寫錯誤或冗餘數據。使用正則表達式修復xml內容

我確實有一個文本處理工具,它可以在沒有任何正則表達式支持的情況下工作,但是如果我可以使用sed或類似的腳本來編寫批量作業並保留一整夜,那麼整個情況會更容易。一個例子的sed腳本應該解決這個問題看起來可能像下面這樣:

#!/bin/sed -f 
s/<prop type="Att::Status">New/<prop type="Att::Status">Not Validated/g 
s/<prop type="Att::Status">Approved/<prop type="Att::Status">Validated/g 
.... 

我發現SED不喜歡UTF16文件太多,因爲我們面對的是雙語XML在34個不同的語言組合,使用像iconv這樣的工具來封裝sed腳本可能會非常危險。大多數字符集轉換工具會導致某種類型的損壞,我寧願不用本週的其餘時間來決定腳本正確運行哪種語言。

還值得一提的是,xml充滿了過去幾年客戶的積累翻譯,所以會有大量的錯誤形式的語法可能會影響某些工具。因此,總之,sed + iconv風險太大,我有一個基本的全局文本替換工具,我有Notepad ++,我甚至有一個在sed語法中用於替換的表達式列表。但有沒有更簡單/更好的方法?

回答

1

請參閱XMLStarlet。這是一個用於讀取/操作XML的命令行工具。

特別是,xml ed命令可能是你想要的。您可以指定要更改內容的XPath,以及如何更改它。它將遵守指定的XML字符編碼等,這是您的標準命令行工具不會的。

+0

感謝。這看起來像是一個很好的前進方向,而不必處理xslt的複雜性。 – IanGilham 2009-04-28 17:56:37

0

我以爲xslt是你最好的選擇。

1

我不知道XML Starlet的複雜性是否比XSLT的複雜性要低 - 大部分複雜性實際上都在XPath中,您將使用它來查找將要使用的節點更改。

如果你使用XSLT,你只需創建一個恆等變換,然後添加一個模板來改變你感興趣的文本節點:

<xsl:template match="prop[@type='Att::Status']/text()"> 
    <xsl:choose> 
     <xsl:when test=". = 'New'">Validated</xsl:when> 
     <xsl:when test=". = 'Approved'">Not Validated</xsl:when> 
     <xsl:otherwise> 
     <xsl:copy/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

或者你可以去堅果和指定映射外部XML文件,如:

<map> 
    <text value="New">Validated</text> 
    <text value="Approved">Not Validated</text> 
</map> 

然後,在你的XSLT:

<xsl:variable name="map" select="document('map.xml')/map/text"/> 

<xsl:template match="prop[@type='Att::Status']/text()"> 
    <xsl:choose> 
     <xsl:when test="$map[@value=current()]"> 
     <xsl:copy-of select="$map[@value=current()]/text()"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:copy/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
+0

似乎相當直接,但語言是如此醜陋。至少XPath相對簡潔明瞭。 +1爲一個很好的例子 – IanGilham 2009-04-30 10:14:38