2012-07-12 63 views
1

我正在尋找用CDATA塊替換轉義的XML部分,主要是爲了提高XML的可讀性,不幸的是必須由人讀取。將轉義的XML文本轉換爲CDATA部分

// Input 
def xml = ''' 
<search> 
    <search-query> 
    &lt;nested/&lt; 
    &lt;xml/&lt; 
    </search-query> 
</search> 
''' 

def search = new XmlParser().parseText(xml) 
def query = search."search-query" 
query.replaceNode() { 
    "search-query"() { 
    // TODO how can I add a CDATA section here? 
    //yieldUnescaped("<![CDATA[${query.text()}]]>") 
    } 
} 

new XmlNodePrinter(preserveWhitespace:true).print(search) 

// Expected 
''' 
<search> 
    <search-query> 
    <![CDATA[<nested/> 
    <xml/>]]> 
    </search-query> 
</search> 
''' 
  • 性能並不重要
  • 我希望能夠使用CDATA只有某些元素

回答

1

使用此XSLT轉換:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output cdata-section-elements="search-query"/> 
<xsl:template match="/"><xsl:copy-of select="."/></xsl:template> 
</xsl:stylesheet> 

您可以替換CDATA -section-elements具有空格分隔的元素名稱列表。

+0

適合工作的工具,我需要保留空白,其Groovy的選擇似乎並沒有這樣做。 使用xmlstarlet完成轉換: '$ xmlstarlet tr cdata.xsl input.xml> output.xml' – 2012-09-25 03:28:27

0

我沒有看到內置API可以幫助您,因爲yield*方法僅適用於將字符串渲染爲字符串(即:使用MarkupBuilder)。 replaceNode方法僅創建新的內存中節點,它們沒有任何方法來表示「原始」內容。

然而,鑑於你有限的樣本,你可能(和我不要喊這表明這一點)是更好只是做字符串替換:

// NOTE: using apache commons because I don't think there's a readily 
//  accessible XML entity parser in Groovy's core libraries. 
@Grab("org.apache.commons:commons-lang3:3.1") 
import org.apache.commons.lang3.StringEscapeUtils 

// Input 
def xml = ''' 
<search> 
    <search-query> 
    &lt;nested/&gt; 
    &lt;xml/&gt; 
    </search-query> 
</search> 
''' 

def converted = xml.replaceAll(/<search-query>([^<]+)<\/search-query/) { 
    def value = StringEscapeUtils.unescapeXml(it[1]) 
    "<search-query><![CDATA[$value]]></search-query>" 
} 

assert converted == ''' 
<search> 
    <search-query><![CDATA[ 
    <nested/> 
    <xml/> 
    ]]></search-query>> 
</se 

剔除阿帕奇百科全書進口,這是很乾淨。如果你不希望看到周圍的嵌套內容的空白,你可以改變unescapeXml(it[1])unescapeXml(it[1].trim())

只有作品,如果XML是正確轉義(意思是,沒有<在部分顯示要被替換) ,並且只有如果您可以安全地根據它的元素確定要替換哪個塊。

1

我可以在Groovy中得到的最接近的是:

import groovy.xml.StreamingMarkupBuilder 
import groovy.xml.XmlUtil 

// Input 
def xml = ''' 
<search> 
    <search-query> 
    &lt;nested/&gt; 
    &lt;xml/&gt; 
    </search-query> 
</search> 
''' 

def nodes = new XmlParser().parseText(xml) 

String newXml = XmlUtil.serialize(new groovy.xml.StreamingMarkupBuilder().bind { 
    search { 
    nodes.'search-query'.each { x -> 
     'search-query' { 
     mkp.yieldUnescaped "<![CDATA[${x.children()}]]>" 
     } 
    } 
    } 
}) 

println newXml 

它打印:

<?xml version="1.0" encoding="UTF-8"?> 
<search> 
    <search-query><![CDATA[[<nested/> 
    <xml/>]]]></search-query> 
</search>