Groovy XmlSlurper:获取具有关联命名空间的属性值
Groovy XmlSlurper: get value of attribute that has an associated namespace
我有一个 XML 文档,其中包含具有限定名称的属性。我想使用 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].@a1.text() == 'uno!'
rootNode.one[0].@a1.text()
将产生一个空字符串。如果使用 rootNode.one[0].'@ex:a1'.text()
我们得到正确的值,但这取决于文档中使用的命名空间前缀 - 并且不能依赖于其他文档相同,关联的命名空间才是最重要的。
所以问题是:
如何使用 XmlSlurper 访问具有关联命名空间的属性的属性值而不需要指定命名空间前缀?
(如果需要提供整个命名空间就可以了)
我找到的唯一解决方案是利用通过将 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!'
更简洁的方法可能是使用 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
我认为如果不指定此类命名空间,则无法访问具有关联命名空间的属性。否则,只有 "local part of the name" 将用于保存属性的地图,导致 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]
有一个更简单的方法:
<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 = parsedXml.@package.text()
def pkg_ver = parsedXml.@'android:versionName'
我有一个 XML 文档,其中包含具有限定名称的属性。我想使用 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].@a1.text() == 'uno!'
rootNode.one[0].@a1.text()
将产生一个空字符串。如果使用 rootNode.one[0].'@ex:a1'.text()
我们得到正确的值,但这取决于文档中使用的命名空间前缀 - 并且不能依赖于其他文档相同,关联的命名空间才是最重要的。
所以问题是: 如何使用 XmlSlurper 访问具有关联命名空间的属性的属性值而不需要指定命名空间前缀? (如果需要提供整个命名空间就可以了)
我找到的唯一解决方案是利用通过将 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!'
更简洁的方法可能是使用 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
我认为如果不指定此类命名空间,则无法访问具有关联命名空间的属性。否则,只有 "local part of the name" 将用于保存属性的地图,导致 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]
有一个更简单的方法:
<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 = parsedXml.@package.text()
def pkg_ver = parsedXml.@'android:versionName'