【问题标题】:Dynamically parsing of XMLs in Groovy在 Groovy 中动态解析 XML
【发布时间】:2022-04-04 22:21:51
【问题描述】:

我有这种格式的 XML:

<message>
  <message_type_id>1</message_type_id>
  <message_type_code>code1</message_type_code>
  <version/>
  <created_at>date1</created_at>
  <payload>
    <payment>
      <document_id>id1</document_id>
      <account_id>id2</account_id>
    </payment>
  </payload>
</message>

未定义有效负载内的分支。在一个 XML 中,它可以有一种结构,而在另一种 XML 中,它可以有另一种结构。

因此,我想要一个像这样的动态数组:

message_type_id: 1
message_type_code: code1
created_at: date1
document_id: id1
account_id: id2

请记住,键 \"document_id\" 和 \"account_id\" 可以有另一个具有不同嵌入级别的结构。 换句话说,我只需要解析每个 XML 树的叶子。而且我不知道这些叶子是怎么命名的,所以结构就像

root.payload.payment.document_id

没用。

我试图用 XmlSlurper 解决这个任务,但没有成功。我该如何解决这个任务?

  • 试过root.\'**\'.document_id
  • @tim_yates 它不起作用。当我执行println root.\'**\'.document_id 时,我收到错误``` 捕获:groovy.lang.MissingPropertyException:没有这样的属性:类的document_id:groovy.xml.slurpersupport.GPathResult$3 groovy.lang.MissingPropertyException:没有这样的属性:类的document_id: groovy.xml.slurpersupport.GPathResult$3 at test.run(test.groovy:20) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)...```
  • 抱歉,试试root.\'**\'.find { it.name() == \'document_id\' }
  • 是的,这个方法有效,谢谢。但问题是一样的 - xml 格式处于开发阶段。不知道明天会有什么标签。所以我想创建一个通用脚本,它将解析所有值,然后将结果放入数组中,其中包含键和值,例如``` message_type_id: 1 message_type_code: code1 created_at: date1 document_id: id1 account_id: id2 ``` 我可以做静态设置对于这些标签(我的意思是所有这些 document_id、account_id),但明天它们可以改变,我不知道什么值和标签。如何使这个解析器通用?
  • @tim_yates 我几乎解决了这个任务。只剩下一步了。 pastebin.com/EHGKZiyA 我收到以下信息:[message:, message_type_id:1, message_type_code:code1, version:, created_at:date1, payload:id1id2, payment:id1id2, document_id:id1, account_id:id2] 应该只有端节点。如何检查节点是否有子节点,如果存在子节点则不添加它们?

标签: xml parsing groovy xmlslurper


【解决方案1】:

所以给定Xml(这里是一个字符串)

def xmlText = '''<message>
  <message_type_id>1</message_type_id>
  <message_type_code>code1</message_type_code>
  <version/>
  <created_at>date1</created_at>
  <payload>
    <payment>
      <document_id>id1</document_id>
      <account_id>id2</account_id>
    </payment>
  </payload>
</message>'''

我们可以用XmlParser解析它:

def message = new XmlParser().parseText(xmlText)

然后找到所有不为空的节点,并且只包含文本(这些是叶子节点)。然后我们可以使用collectEntries 从中制作地图:

def map = message.'**'.findAll {
         !it.children().empty &&                        // Ignore empty leaves
          it.children().every { it instanceof String }  // Leaves only contain strings
}.collectEntries {
    [it.name(), it.text()]
}

这会将以下内容分配给变量map

[
    message_type_id: "1",
    message_type_code: "code1",
    created_at: "date1",
    document_id: "id1",
    account_id: "id2"
]

但是,如果节点具有相同的名称,您将遇到问题(因为地图只能包含一个键)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    相关资源
    最近更新 更多