2015-10-29 1 views
3

При ответа на этот вопрос How to read values from XML Request and write into XML Response using Groovy?, связанный с пространствами имен (SOAP) с XmlSlurper и XmlParser, я понял, что я на самом деле не в состоянии сказать, если они без пространства имен известны по умолчанию.Пространство имен XmlParser и XmlSlurper известно по умолчанию?

Хотя документация говорит так (без пространства имен известно по умолчанию):

XmlSlurper

XmlSlurper()

Создает непроверяющий и не-namespace-aware XmlSlurper, который не все декларации DOCTYPE в документах.

XmlParser

XmlParser()

Создает непроверяющий и не пространства имен-Aware XMLParser, которая не позволяет декларации DOCTYPE в документах.

Код ровно наоборот (пространства имен по умолчанию известно):

XmlSlurper:

public XmlSlurper() throws ParserConfigurationException, SAXException { 
    this(false, true); 
} 

XmlParser:

public XmlParser() throws ParserConfigurationException, SAXException { 
    this(false, true); 
} 

Я нашел также это answer, заявляя, что XMLSlurper не является пространством имен, которое известно по умолчанию.

ответ

1

По состоянию на Groovy 2.4.6, документация неправильно:

/** 
* Creates a non-validating and non-namespace-aware <code>XmlSlurper</code> which does not allow DOCTYPE declarations in documents. 
* 
* @throws ParserConfigurationException if no parser which satisfies the requested configuration can be created. 
* @throws SAXException for SAX errors. 
*/ 
public XmlSlurper() throws ParserConfigurationException, SAXException { 
    this(false, true); 
} 

Это фактически создает парсер, ориентированный на пространство имен (второй параметр true).

Существует также ошибка, о которой я сообщал, где префиксы пространства имен не обрабатываются должным образом: https://issues.apache.org/jira/browse/GROOVY-7781. К счастью, другой пользователь выпустил PR для исправления. Кто-то должен поставить PR, чтобы исправить проблему с документацией, а также несколько раз заблуждался для меня и других.

+0

Я поставил PR для документа: https://github.com/apache/groovy/pull/305 –

2

Я думаю, что документация является неправильной и XmlSlurper и XmlParser являются пространства имен известны по умолчанию:

def text = '''<person xmlns:city="http://localhost/"> 
    <name>jalopaba</name> 
    <city:name>Valladolid</city:name> 
</person>''' 

// XmlSlurper is namespace aware, since new XmlSlurper() --> new XmlSlurper(false, true) 
def slurped_person = new XmlSlurper().parseText(text) 
assert 'jalopabaValladolid' == slurped_person.name.text() // :name and :name from city 
assert 'jalopaba' == slurped_person.':name'.text() // aware of default namespace 
assert '' == slurped_person.'city:name'.text() // city namespace not declared 

// but you need to make the resulting GPathResult aware of the concrete namespace 
slurped_person = new XmlSlurper().parseText(text).declareNamespace([city: 'http://localhost/']) 
assert 'jalopabaValladolid' == slurped_person.name.text() // :name and :name from city 
assert 'jalopaba' == slurped_person.':name'.text() // aware of default namespace 
assert 'Valladolid' == slurped_person.'city:name'.text() // city namespace declared 

// If you make XmlSlurper not namespace aware, it uses the whole element string 
slurped_person = new XmlSlurper(false, false).parseText(text) 
assert 'jalopaba' == slurped_person.name.text() // just element 'name' 
assert '' == slurped_person.':name'.text() // not aware of default namespace 
assert 'Valladolid' == slurped_person.'city:name'.text() // using the whole element string (it seems to be namespace aware, but it's not) 

// And when it is not namespace aware, nothing changes declaring namespaces 
slurped_person = new XmlSlurper(false, false).parseText(text).declareNamespace([city: 'http://localhost/']) 
assert 'jalopaba' == slurped_person.name.text() // just element 'name' 
assert '' == slurped_person.':name'.text() // not aware of default namespace 
assert 'Valladolid' == slurped_person.'city:name'.text() // using the whole element string (it seems to be namespace aware, but it's not) 

def c = new Namespace('http://localhost/', 'city') 
assert c.name instanceof QName // => new QName('http://localhost/', 'name', 'city') 

// XmlParser is namespace aware, since new XmlParser() --> new XmlParser(false, true) 
def parsed_person = new XmlParser().parseText(text) 
assert parsed_person.toString() == 'person[attributes={}; value=[name[attributes={}; value=[jalopaba]], {http://localhost/}name[attributes={}; value=[Valladolid]]]]' 
assert 'jalopaba' == parsed_person.name.text() // default namespace 
assert 'jalopaba' == parsed_person[new QName('name')].text() // default namespace 
assert 'jalopabaValladolid' == parsed_person[new QName('http://localhost/', 'name')].text() // aware of namespace and empty string as prefix 
assert 'Valladolid' == parsed_person[new QName('http://localhost/', 'name', 'it_does_not_matter')].text() // aware of namespace, prefix does not matter 
assert '' == parsed_person[new QName('http://wrong_namespace/', 'name', 'city')].text() // aware of namespace, wrong URI with good prefix gets nothing 
assert 'Valladolid' == parsed_person[c.name].text() 
assert 'Valladolid' == parsed_person.'city:name'.text() // using the whole element string 

// With XmlParser not namespace aware... 
parsed_person = new XmlParser(false, false).parseText(text) 
assert parsed_person.toString() == 'person[attributes={xmlns:city=http://localhost/}; value=[name[attributes={}; value=[jalopaba]], city:name[attributes={}; value=[Valladolid]]]]' 
assert 'jalopaba' == parsed_person.name.text() 
assert 'jalopaba' == parsed_person[new QName('name')].text() 
assert 'jalopaba' == parsed_person[new QName('http://localhost/', 'name')].text() // ignores namespace, only uses 'name' string 
assert '' == parsed_person[new QName('http://localhost/', 'name', 'wrong_prefix')].text() // not aware of namespace, the only important thing is prefix 
assert 'Valladolid' == parsed_person[new QName('http://wrong_namespace/', 'name', 'city')].text() // wrong namespace but not aware, the only important thing is prefix 
assert 'Valladolid' == parsed_person[c.name].text() 
assert 'Valladolid' == parsed_person.'city:name'.text() 
Смежные вопросы