2013-08-18 5 views
3

Анализ XML в Groovy должен быть куском пирога, но я всегда сталкиваюсь с проблемами.Анализ XML в Groovy с пространством имен и объектами

Я хотел бы разобрать строку, как это:

<html> 
<p> 
This&nbsp;is a <span>test</span> with <b>some</b> formattings.<br /> 
And this has a <ac:special>special</ac:special> formatting. 
</p> 
</html> 

Когда я делаю это стандартный способ new XmlSlurper().parseText(body), анализатор жалуется на &nbsp лица. Мое секретное оружие в таких случаях, как это использовать TagSoup:

def parser = new org.ccil.cowan.tagsoup.Parser() 
def page = new XmlSlurper(parser).parseText(body) 

Но теперь <ac:sepcial> тег будет закрыт немедленно анализатор - special текста не будет находиться внутри данного тега, в результате йота. Даже когда я вывожу пространство имен-функции:

def parser = new org.ccil.cowan.tagsoup.Parser() 
parser.setFeature(parser.namespacesFeature,false) 
def page = new XmlSlurper(parser).parseText(body) 

Другой подход заключается в использовании стандартного парсер и добавить доктайп как этот:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

Это, кажется, работает для большинства моих файлов, но для анализатора требуется много времени, чтобы получить dtd и обработать его.

Любая хорошая идея, как это решить?

PS: вот некоторые примеры кода, чтобы поиграть с:

@Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='0.9.7') 
def processNode(node) { 
    def out = new StringBuilder("") 
    node.children.each { 
     if (it instanceof String) { 
      out << it 
     } else { 
      out << "<${it.name()}>${processNode(it)}</${it.name()}>" 
     } 
    } 
    return out.toString() 
} 

def body = """<html> 
<p> 
This&nbsp;is a <span>test</span> with <b>some</b> formattings.<br /> 
And this has a <ac:special>special</ac:special> formatting. 
</p> 
</html>""" 

def parser = new org.ccil.cowan.tagsoup.Parser() 
parser.setFeature(parser.namespacesFeature,false) 
def page = new XmlSlurper(parser).parseText(body) 
def out = new StringBuilder("") 
page.childNodes().each { 
    out << processNode(it) 
} 
println out.toString() 
"" 

ответ

2

Вы должны решить, хотите ли вы разборе, чтобы соответствовать стандартам, идя по пути ОТД, или принять только что-нибудь с разрешающим анализатором ,

Теги в моем опыте отлично подходят для последнего, и он редко создает какие-либо проблемы, поэтому я был удивлен, прочитав ваше замечание об обработке «специального». Быстрый тест показал также, что я не мог воспроизвести его: при выполнении этой команды

java net.sf.saxon.Query -x:org.ccil.cowan.tagsoup.Parser -s:- -qs:. !encoding=ASCII !indent=yes 

на образец, я получил этот результат

<?xml version="1.0" encoding="ASCII"?> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:html="http://www.w3.org/1999/xhtml"> 
    <body> 
     <p> 
    This&#xa0;is a <span>test</span> with <b>some</b> formattings.<br clear="none"/> 
    And this has a <ac:special xmlns:ac="urn:x-prefix:ac">special</ac:special> formatting. 
    </p> 

    </body> 
</html> 

от обоих TagSoup 1,2 и 1.2.1. Поэтому для меня, как и следовало ожидать, текст «специальный» появляется внутри тега «ac: special».

Что касается варианта DTD, вы можете следить за прохождением кэширования для разрешения DTD, ссылаться на локальную копию или даже уменьшать DTD до минимального необходимого вам уровня. Для того, чтобы провести вас через объект &nbsp;, должно быть достаточно:

<!DOCTYPE DOC[<!ENTITY nbsp "&#160;">]> 
+0

Отлично! Это была версия парсера tagoup, который я использовал (0.9.x) ... 1.2.1 отлично работает для меня. Thanx! – rdmueller