2015-03-05 3 views
4

У меня есть документ XML, содержащий атрибуты с квалифицированными именами. Я хочу получить значение атрибута с помощью XmlSlurper, но попытка доступа к атрибуту без указания пространства имен не работает (ниже приведен минимальный пример).Groovy XmlSlurper: получить значение атрибута, имеющего связанное пространство имен

def rootNode = new XmlSlurper().parseText(
'''<root xmlns:ex="http://example.com"> 
    <one ex:a1="uno!"/> 
    <ex:two>Some text!</ex:two> 
    </root>''') 

assert rootNode.one[0][email protected]() == 'uno!' 

rootNode.one[0][email protected]() даст пустую строку. Если вы используете rootNode.one[0].'@ex:a1'.text(), мы получаем правильное значение, но это зависит от префикса пространства имен, используемого в документе, - и на него нельзя полагаться одинаковым для других документов, что важно для соответствующего пространства имен.

Так что вопрос: Как XmlSlurper можно использовать для доступа к значению атрибута атрибута, который имеет связанные с ним пространство имен без необходимости указывать префикс пространства имен? (было бы нормально, если бы потребовалось полное пространство имен)

ответ

5

Я думаю, что доступ к атрибуту с соответствующим пространством имен может» t быть сделано без указания такого пространства имен. В противном случае для карты, содержащей атрибуты, будет использоваться только «локальная часть имени», что приведет к ситуациям, например this old bug (groovy 1.7.5).

Может быть, лучший способ сделать это состоит в использовании groovy.xml.Namespace и использовать его для доступа к атрибуту:

import groovy.xml.Namespace 

def xml = ''' 
<root xmlns:ex="http://example.com"> 
    <one ex:a1="uno!"/> 
    <ex:two>Some text!</ex:two> 
</root>''' 
def ns = new Namespace('http://example.com', 'ex') 

def slurper = new XmlSlurper(false, true) 
def slurped = slurper.parseText(xml) 
assert 'uno!' == slurped.one[0].attributes()[ns.a1.toString()] 

def parser = new XmlParser(false, true) 
def parsed = parser.parseText(xml) 
assert 'uno!' == parsed.one[0].attributes()[ns.a1] 
+0

Я согласен, что доступ к атрибутам без пространства имен может привести к беспорядочным ситуациям, но sometim es удобно использовать пространство имен независимо. С XmlSlurper неожиданно, что он ведет себя так по-разному для элементов и атрибутов - 'slurped.two [0]' даст элемент с соответствующим пространством имен, в то время как он не делает то же самое для атрибутов. – stempler

+0

Я согласен с вами в этом ... Это немного вводит в заблуждение, что XmlSlurper ведет себя по-разному для элементов и атрибутов. Кроме того, вы можете создать XmlSlurper с «namespaceAware = false», но в этом случае ключ карты атрибутов «ex: a1» вместо '{http://example.com} a1'. – jalopaba

1

Единственное, что я нашел, это использование возможности доступа к атрибутам через представление GPathResult как Node.

Рабочий пример выглядит следующим образом:

def rootNode = new XmlSlurper().parseText(
'''<root xmlns:ex="http://example.com"> 
    <one ex:a1="uno!"/> 
    <ex:two>Some text!</ex:two> 
    </root>''') 

// map of attributes, or null 
def oneAttrs = rootNode.one[0].nodeIterator().next()?.attributes() 
assert oneAttrs 
// retrieve attribute by qualified name 
assert oneAttrs['{http://example.com}a1'] == 'uno!' 
3

уборщик метод может быть использование find и localPart с XmlParser:

def rootNode = new XmlParser().parseText(
'''<root xmlns:ex="http://example.com"> 
    <one ex:a1="uno!"/> 
    <ex:two>Some text!</ex:two> 
    </root>''') 

rootNode.one[0].attributes().find { it.key.localPart == 'a1' }?.value 
1

Там есть более простой способ:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    android:versionCode="500" android:versionName="5.0.0" package="com.my.package" 
    android:installLocation="preferExternal" > 
... 
</manifest > 

разборе Attr с пространством имен и без:

def parsedXml = (new XmlSlurper()).parse(android.sourceSets.main.manifest.srcFile) 
def pkg_name = [email protected]() 
def pkg_ver = [email protected]'android:versionName' 
+0

Да, но это не решает проблему. Как упоминалось в вопросе, мы получаем правильное значение, подобное этому, но оно зависит от префикса пространства имен, используемого в документе, - и на него нельзя полагаться одинаковым для других документов, что важно для соответствующего пространства имен. Таким образом, при таком подходе необходимо сначала определить префикс пространства имен. Но поскольку префикс для пространства имен может быть определен и переопределен на любом элементе XML, это не так просто. – stempler

Смежные вопросы