groovy - 如何确定NodeChild中给定属性的命名空间

标签 groovy xml-parsing

我正在尝试使用 XmlSlurper 解析一些 Android XML .对于给定的子节点,我想检测是否指定了具有特定命名空间的属性。

例如,在下面的 XML 中,我想知道 EditText节点已经声明了来自“b”命名空间的任何属性:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:b="http://x.y.z.com">

    <EditText
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        b:enabled="true" />

</LinearLayout>

我首先调用:
 def rootNode = new XmlSlurper().parseText(text)

获取对根的句柄 GPathResult .当我遍历 child 时,我得到了一个 groovy.util.slurpersupport.NodeChild 的实例。 .在这个类中,我可以通过调用 attributes() 来检查属性。在 EditText 的情况下上面,这将返回以下 map :[layout_width: "fill_parent", layout_height: "wrap_content", enabled: "true"] .

这一切都很好。但是,似乎没有办法查询给定属性的命名空间。我在这里错过了什么吗?

最佳答案

您可以使用 XmlParser而不是 XmlSlurper并这样做:

def xml = '''<LinearLayout
            |    xmlns:android="http://schemas.android.com/apk/res/android"
            |    xmlns:b="http://x.y.z.com">
            |
            |  <EditText
            |      android:layout_width="fill_parent"
            |      android:layout_height="wrap_content"
            |      b:enabled="true" />
            |</LinearLayout>'''.stripMargin()

def root = new XmlParser().parseText( xml )

root.EditText*.attributes()*.each { k, v ->
  println "$k.localPart $k.prefix($k.namespaceURI) = $v"
}

哪个打印出来
layout_width android(http://schemas.android.com/apk/res/android) = fill_parent
layout_height android(http://schemas.android.com/apk/res/android) = wrap_content
enabled b(http://x.y.z.com) = true

编辑

要使用 XmlSlurper,首先需要访问 namespaceTagHints使用反射来自根节点的属性:
def rootNode = new XmlSlurper().parseText(xml)

def xmlClass = rootNode.getClass()
def gpathClass = xmlClass.getSuperclass()
def namespaceTagHintsField = gpathClass.getDeclaredField("namespaceTagHints")
namespaceTagHintsField.setAccessible(true)

def namespaceDeclarations = namespaceTagHintsField.get(rootNode)
namespaceTagHintsGPathResult 的属性(property),它是 NodeChild 的父类(super class).

然后,您可以交叉引用此映射以访问命名空间前缀并打印出与上述相同的结果:
rootNode.EditText.nodeIterator().each { groovy.util.slurpersupport.Node n ->
  n.@attributeNamespaces.each { name, ns ->
    def prefix = namespaceDeclarations.find {key, value -> value == ns}.key
    println "$name $prefix($ns) = ${n.attributes()"$name"}"
  }
}

关于groovy - 如何确定NodeChild中给定属性的命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9104496/

相关文章:

c - 如何使用 libxml2 库在 c 中解析 XML 字符串而不是 XML 文档

string - 什么函数用于格式化/替换 Grails/Groovy 中字符串中的 {0} {1} 参数?

grails - 在 Groovy 中测试图像验证

java - 泛型上的 Groovy 映射和 Java 映射

python - 如何在 Python 中获取两个 xml 标记之间的全部内容?

ruby - 如何让 Nokogiri 解析并返回 XML 文档?

css - 将 XML 解析为 XHTML 以应用 CSS 的最简单方法

grails - Grails BuildConfig中的IntelliJ mavenLocal警告

java - 如何在 Eclipse 中更改 DSLD 编译类路径

c# - 将无效字符解析为 XML