1

エスケープされたXMLセクションをCDATAブロックに置き換えることを検討しています。これは主に、残念ながら人間が読み取らなければならないXMLの可読性を向上させるためです。

// 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を使用できるようにしたい
4

3 に答える 3

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>
于 2012-07-12T08:02:45.773 に答える
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 をスペースで区切られた要素名のリストに置き換えることができます。

于 2012-07-12T07:56:19.350 に答える
0

yield*メソッドは文字列にレンダリングする場合 (つまり、MarkupBuilder を使用する場合) にのみ適用されるため、組み込み API が役立つ方法はありません。この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

Apache Commons のインポートを除けば、かなりきれいです。ネストされたコンテンツの周りの空白を見たくない場合は、次のように変更できunescapeXml(it[1])ますunescapeXml(it[1].trim())

これは、XML が適切にエスケープされている (つまり、置換されるセクションに表示されない) 場合にのみ機能し、要素に基づいて置換するブロックを安全に判断できる場合にのみ機能します。<

于 2012-07-12T07:57:29.973 に答える