scala 中的递归 XML
我正在尝试用 scala 解析此文档:
<?xml version="1.0"?>
<model>
<joint name="pelvis">
<joint name="lleg">
<joint name="lfoot"/>
</joint>
<joint name="rleg">
<joint name="rfoot"/>
</joint>
</joint>
</model>
我想用它为我的 2d 动画引擎创建一个骨架。每个关节都应该制作成相应的对象,并将所有子对象添加到其中。
所以这部分应该产生与此类似的结果:
j = new Joint("pelvis")
lleg = new Joint("lleg")
lfoot = new Joint("lfoot")
rleg = new Joint("rleg")
rfoot = new Joint("rfoot")
lleg.addJoint(lfoot)
rleg.addJoint(rfoot)
j.addJoint(lleg)
j.addJoint(rleg)
但是,我在浏览 xml 代码时遇到了问题。一方面,我不确定我是否完全理解语法 xml \\ "joint"
,它似乎会生成一个包含所有标签的 NodeSeq。
主要问题:
- 理解 scala 中 xml 语法的问题,即
xml \\ "...", Elem.child?,
- 从父节点获取属性而不从所有子节点获取属性时出现问题 (
xml \\ "@attribute"
,生成所有属性的串联..?)
I am trying to parse this document in scala:
<?xml version="1.0"?>
<model>
<joint name="pelvis">
<joint name="lleg">
<joint name="lfoot"/>
</joint>
<joint name="rleg">
<joint name="rfoot"/>
</joint>
</joint>
</model>
I want to use it to create a skeleton for my 2d-animation engine. Every joint should be made into the according object and all the children added to it.
So this part should produce a result similar to this:
j = new Joint("pelvis")
lleg = new Joint("lleg")
lfoot = new Joint("lfoot")
rleg = new Joint("rleg")
rfoot = new Joint("rfoot")
lleg.addJoint(lfoot)
rleg.addJoint(rfoot)
j.addJoint(lleg)
j.addJoint(rleg)
However, I am having trouble going through the xml code. For one thing, I am not sure I completely understand the syntax xml \\ "joint"
, which seems to produce a NodeSeq containing all tags.
Main problems:
- Problem understanding syntax with xml in scala, i.e.
xml \\ "...", Elem.child?,
- Problem getting an attribute from a parent node without getting attributes from all children (
xml \\ "@attribute"
, produces a concat of all attributes..?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
运算符
\\
是一个类似 XPath 的运算符。它将“选择”所有具有某种特征的后代。这可以通过两遍来完成,如下所示:
我想我更喜欢递归解决方案,但这应该是相当可行的。
The operator
\\
is an XPath-like operator. It will "select" all descendants with a certain characteristic.This could be done in two passes like this:
I think I would prefer a recursive solution, but this should be quite workable.
使用 xtract 可以轻松完成此操作。
请注意如何使用
lazyRead
,以便可以递归地使用Joint
的读取器。这篇博文更详细地讨论了 xtract:https://www.lucidchart.com/techblog/2016/07/12/introducing-xtract-a-new-xml-deserialization-library-for-scala/
免责声明:我在 Lucid Software 工作,并且是 xtract 的主要贡献者。
This can be done pretty easily using xtract.
Note how
lazyRead
is used so, that the reader forJoint
can be used recursively.This blog post, talks about xtract in more detail: https://www.lucidchart.com/techblog/2016/07/12/introducing-xtract-a-new-xml-deserialization-library-for-scala/
Disclaimer: I work for Lucid Software, and am a major contributor to xtract.
还有一个使用
scala.xml.pull.XMLEventReader
的解决方案:这是 Scala 2.8。
我已经发布了完整的源代码 此处。处理模型确实是顺序的,但效果很好,因为每个开放标记都将指示我们需要创建一个 Joint 对象,可以选择将其添加到父对象并存储为新的父对象。关闭标签会根据需要弹出父标签。
There is also a solution with the
scala.xml.pull.XMLEventReader
:This is Scala 2.8.
I have posted the complete source here. The processing model is really sequential, but that works well since every open tag will indicate that we need to create a Joint object, optionally add it to the parent and store as the new parent. Close tags pops parent as necessary.