Groovy Node.depthFirst() 返回节点和字符串列表?

2024-01-19

我希望有人能指出我在这里遗漏的一些明显的东西。我觉得我已经这样做了一百次了,出于某种原因,今晚,由此产生的行为让我陷入了困境。

我正在从公共 API 读取一些 XML。我想从某个节点中提取所有文本(“body”内的所有内容),其中还包括各种子节点。简单的例子:

<xml>
    <metadata>
        <article>
            <body>
                <sec>
                    <title>A Title</title>
                    <p>
                        This contains 
                        <italic>italics</italic> 
                        and
                        <xref ref-type="bibr">xref's</xref>
                        .
                    </p>
                </sec>
                <sec>
                    <title>Second Title</title>
                </sec>
            </body>
        </article>
    </metadata>
</xml>

因此,最终我想遍历所需节点(同样是“主体”)内的树,并提取以其自然顺序包含的所有文本。很简单,所以我只写了这个 Groovy 小脚本......

def xmlParser = new XmlParser()
def xml = xmlParser.parseText(rawXml)
xml.metadata.article.body[0].depthFirst().each { node ->
    if(node.children().size() == 1) {
        println node.text()
    }   
}

...它会因“没有方法签名:java.lang.String.children()”而爆炸。所以我心里想“等等,什么?我是不是疯了?” Node.depthFirst() 应该只返回 Node 的列表。我添加了一些“instanceof”检查,果然,我得到了 Node 对象和 String 对象的组合。具体来说,不在同一行上的实体内的行将作为字符串返回,即“This contains”和“and”。其他一切都是节点(如预期)。

我可以轻松解决这个问题。然而,这似乎不是正确的行为,我希望有人能指出我正确的方向。


我很确定这是正确的行为(尽管我总是发现 XmlSlurper 和 XmlParser 有奇怪的 API)。在我看来,所有你可以迭代的东西都应该实现一个节点接口,并且可能有一个type of TEXT您可以用它来了解从他们那里获取文本。

这些文本节点是有效节点,在许多情况下您希望在它对 XML 进行深度优先遍历时命中它们。如果它们没有返回,则用于检查子节点大小是否为 1 的算法将不起作用,因为某些节点(例如<p>标签)下面有混合文本和元素。

还有,为什么depthFirst并不始终返回文本是唯一子节点的所有文本节点,例如 foritalic上面,让事情变得更糟。

我倾向于使用常规方法的签名来让运行时找出处理每个节点的正确方法(而不是使用类似的方法)instanceof) 像这样:

def rawXml = """<xml>
    <metadata>
        <article>
            <body>
                <sec>
                    <title>A Title</title>
                    <p>
                        This contains 
                        <italic>italics</italic> 
                        and
                        <xref ref-type="bibr">xref's</xref>
                        .
                    </p>
                </sec>
                <sec>
                    <title>Second Title</title>
                </sec>
            </body>
        </article>
    </metadata>
</xml>"""

def processNode(String nodeText) {
    return nodeText
}

def processNode(Object node) {
   if(node.children().size() == 1) {
       return node.text()
   }
}

def xmlParser = new XmlParser()
def xml = xmlParser.parseText(rawXml)
def xmlText = xml.metadata.article.body[0].'**'.findResults { node ->
    processNode(node)
}

println xmlText.join(" ")

Prints

A Title This contains italics and xref's .  Second Title

或者,XmlSlurper类可能会做更多你想要/期望的事情,并且有一组更合理的输出text()方法。如果你真的不需要对结果进行任何类型的 DOM 遍历(什么XmlParser是“更好”),我建议XmlSlurper:

def xmlParser = new XmlSlurper()
def xml = xmlParser.parseText(rawXml)
def bodyText = xml.metadata.article.body[0].text()
println bodyText

Prints:

A Title
                    This contains 
                    italics 
                    and
                    xref's
                    .
                Second Title
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Groovy Node.depthFirst() 返回节点和字符串列表? 的相关文章

随机推荐

  • 有没有一种快速方法可以在音频文件中查找(不一定识别)人类语音?

    我想编写一个程序 自动同步未同步的字幕 我想到的解决方案之一是以某种方式通过算法找到人类语音并根据其调整字幕 我发现的 API Google Speech API Yandex SpeechKit 与服务器一起工作 这对我来说不太方便 并且
  • SwiftUI 模态演示仅在 navigationBarItems 中工作一次

    当您从导航栏项目内的按钮显示模式时 SwiftUI 中存在一个错误 在下面的代码中 按钮 1 按预期工作 但按钮 2 只工作一次 struct DetailView View Binding var isPresented Bool Env
  • 为什么不能使用具有多态返回类型的原始类型?

    考虑以下两个类 public interface Foo
  • 将 Java BigInteger 用于巨大位掩码的性能影响

    我们面临着一个有趣的挑战 我们必须控制对驻留在 容器 中的数据的访问 可能会有数十万个 垃圾箱 对每个垃圾箱的访问是单独控制的 但限制可能而且可能会重叠 我们正在考虑为每个 bin 分配位掩码中的一个位置 1 2 3 4 等 然后 当用户登
  • 使用参数 [null, 2, 3] 执行“INSERT INTO events (user_id, ET1, ET2) VALUES (?, ?, ?)”时发生异常:

    我正在尝试从默认控制器内部创建表单 我希望主页中两个下拉列表中的值都存储在事件表的 ET1 和 ET2 列中 我能够做到这一点 但是我希望登录用户的 user id 也应该存储在事件表的 user id 列中 当尝试这样做时 它给了我错误
  • 方法 Illuminate\Database\Eloquent\Collection::links 不存在

    我创建了用户和消息之间的模型关系 我想为经过身份验证的用户实现消息列表 但出现以下错误 方法 Illuminate Database Eloquent Collection links 不存在 控制器 public function ind
  • 当我使用快捷键时获取我的ContextMenuStrip的SourceControl

    我有单身ContextMenuStrip连接到两个控件 DataGridView In the ToolStripMenuItem单击事件 我设法得到原始调用者 DataGridView 用这个代码 var menu ToolStripDr
  • 查找 Excel 电子表格的模板路径

    我有一个带有 VBA 代码的 Excel 电子表格模板 xltm 文件 我想在模板打开的电子表格中找到模板的路径 问题示例 用户通过双击 C My Stuff 中的模板文件打开一个新电子表格 他们填写单元格 然后在询问他们的名称后单击一个按
  • MySQL所有父子关系

    我有一个名为table 它有一个名为id与类型INT 11 代表行的标识符 它还有其他字段 但我认为它们与这个问题无关 我有另一个表名为table children 它有一个名为parent与类型INT 11 指的是table id作为外键
  • 使用 1 位 ALU 制作 16 位 ALU

    你好 我正在尝试从几个 1 位 ALU 创建一个 16 位 ALU 我创建了一个名为 basic alu1 的包 其中包含 1 位 ALU 的组件 其代码是 library ieee use ieee std logic 1164 all
  • Arduino 中的字符串比较

    我正在开发基于网络的家庭自动化系统 因此我的Arduino向服务器发送请求并在串行监视器中获得以下响应以及 loneOn 这是由于Serial println r 陈述 HTTP 1 1 200 OK Date Mon 13 Oct 201
  • 使用 Boost.python 将 Python 列表传递给 C++ 向量

    如何传递对象类型的 Python 列表ClassName到一个接受a的C 函数vector
  • 如何防止我的应用程序在 iPhone 上后台运行

    有什么方法可以让应用程序在按下主页按钮时退出而不是进入后台吗 出于安全原因 如果应用程序不在后台运行 而是在按下主页时实际关闭 那就更好了 这是not为了用户的安全 而是为了应用程序上的公司数据 所以这不是用户的选择 除了强行退出之外 我找
  • Nodejs/V8 是否将编译后的机器代码存储在磁盘上的任何位置?

    Edit Node 从 Node 8 3 开始使用字节码 在此之前 源代码直接编译为机器代码 我进行了大量的 Python 编码 并且 pyc 文件中总是存在字节码 我想知道节点是否将其机器代码存储在类似的文件中 例如 将机器代码表示保留
  • 网络摄像机RTSP地址

    我有 IP 摄像头 但我不知道它是 RTSP 流的完整正确 URL 地址 仅 RTSP 设置中有端口 但据我了解 192 168 1 132 554 还不够 VLC 说找不到 rtsp 流 如何找出正确的 url 地址 如何找出正确的 ur
  • 复合主键是否为N-M关系?

    假设我们有 3 个表 实际上我现在有 2 个表 但这个例子可能会更好地说明这个想法 Person ID int 主键 名称 nvarchar xx Group ID int 主键 名称 nvarchar xx Role ID int 主键
  • Android Java:关闭屏幕

    我正在制作一个使用接近传感器打开和关闭屏幕的应用程序 接近代码已完成 但我在使用屏幕控件时遇到了麻烦 我读过我应该使用 PowerManager manager PowerManager getSystemService Context P
  • 为什么 MFMailComposeViewController 返回 MFMailComposeResultFailed?

    我的应用程序遇到一个奇怪的问题 我需要您的帮助 我正在使用 MFMailComposeViewController 发送带有附件数据的电子邮件 附件是 PDF CSV 或 XLS 文件 还可以将 ZIP 文件添加到邮件中 在大多数情况下一切
  • 关闭窗口前Socket.IO断开连接问题

    我试图阻止客户端与服务器断开连接 因此 在用户关闭打开应用程序的窗口之前 我会执行以下操作 window bind beforeunload function return Close the app 但问题是 无论用户选择离开还是留在应用
  • Groovy Node.depthFirst() 返回节点和字符串列表?

    我希望有人能指出我在这里遗漏的一些明显的东西 我觉得我已经这样做了一百次了 出于某种原因 今晚 由此产生的行为让我陷入了困境 我正在从公共 API 读取一些 XML 我想从某个节点中提取所有文本 body 内的所有内容 其中还包括各种子节点