如何在 Scala 中解析带有重复标签的 XML,提取库?
How do I parse XML with repetetive tags in Scala, xtract library?
我遇到以下问题:
我正在使用 [xtract][1],一个用于解析 XMLs 的 Scala 库。最新版本,2.0.0
我正在尝试像这样解析 XML 文件
<annotation>
<folder>home</folder>
<filename>source</filename>
<source>
<database>Unknown</database>
</source>
<object>
<name>name1</name>
<truncated>0</truncated>
<difficult>1</difficult>
</object>
<object>
<name>name2</name>
<truncated>1</truncated>
<difficult>1</difficult>
</object>
</annotation>
这是我的 class 我正在将 XML 解析为:
case class MyObject(
name: String,
truncated: Boolean
)
trait MyObjectXml{
implicit val xmlReader: XmlReader[MyObject] = (
(__ \ "object" \ "name").read[String],
(__ \ "object" \ "truncated").read[Boolean]
).mapN(MyObject.apply)
}
object MyObjectXml extends MyObjectXmlXml
这里我做解析:
//open an XML file
val xml = scala.xml.XML.loadString(
bufferedSource
.getLines()
.mkString("\n")
)
XmlReader.seq[MyObject].read(xml) match {
case ParseSuccess(seatsXml) => ...
case ParseFailure(errors) => ...
case PartialParseSuccess(geometry, errors) => ...
}
我遇到了 ParseFailure:
List(MultipleMatchesError(/object/name), MultipleMatchesError(/object/truncated))
[错误][2]表示该路径匹配多个节点,而预期只有一个。
所以我想要的是获得一个 Seq[MyClass]。我如何告诉 XMLReader 我想将所有重复的标签解析为一个序列?我认为应用 .seq[T] 会做到这一点,但事实并非如此。
非常感谢您的帮助!
Upd.: 抱歉,我项目中的 xtract 版本确实是 2.2.1,而不是 2.2.0 我刚刚查看了 README 并希望在那里看到最新的版本号
[1]: https://github.com/lucidsoftware/xtract
[2]: http://lucidsoftware.github.io/xtract/core/api/com/lucidchart/open/xtract/MultipleMatchesError.html
您的代码存在几个问题。路径 object/name
确实有歧义,因为你不知道你指的是第一个还是第二个。
首先,你需要定义一个包含所需序列的class,它的reader:
case class MyObjects(myObjects: Seq[MyObject])
object MyObjects {
implicit val reader: XmlReader[MyObjects] = (__ \ "object").read(seq[MyObject]).map(apply)
}
现在,由于此对象读取路径的 object
部分,我们需要从 MyObject
中省略该部分,这意味着它应该是:
case class MyObject(name: String, truncated: Boolean)
object MyObject {
implicit val xmlReader: XmlReader[MyObject] = (
(__ \ "name").read[String],
(__ \ "truncated").read[Boolean]
).mapN(MyObject.apply)
}
另一个问题是您将 truncated
解析为布尔值,但该值实际上是一个整数。所以我将 xml 更改为包含布尔值。
最后,为了阅读,我们可以这样做:
XmlReader.of[MyObjects].read(xml) match {
case ParseSuccess(seatsXml) => println(seatsXml)
case ParseFailure(errors) => println(errors)
case PartialParseSuccess(geometry, errors) => println(errors)
}
输出为:
MyObjects(Vector(MyObject(name1,false), MyObject(name2,true)))
代码 运行 在 Scastie。
我遇到以下问题: 我正在使用 [xtract][1],一个用于解析 XMLs 的 Scala 库。最新版本,2.0.0 我正在尝试像这样解析 XML 文件
<annotation>
<folder>home</folder>
<filename>source</filename>
<source>
<database>Unknown</database>
</source>
<object>
<name>name1</name>
<truncated>0</truncated>
<difficult>1</difficult>
</object>
<object>
<name>name2</name>
<truncated>1</truncated>
<difficult>1</difficult>
</object>
</annotation>
这是我的 class 我正在将 XML 解析为:
case class MyObject(
name: String,
truncated: Boolean
)
trait MyObjectXml{
implicit val xmlReader: XmlReader[MyObject] = (
(__ \ "object" \ "name").read[String],
(__ \ "object" \ "truncated").read[Boolean]
).mapN(MyObject.apply)
}
object MyObjectXml extends MyObjectXmlXml
这里我做解析:
//open an XML file
val xml = scala.xml.XML.loadString(
bufferedSource
.getLines()
.mkString("\n")
)
XmlReader.seq[MyObject].read(xml) match {
case ParseSuccess(seatsXml) => ...
case ParseFailure(errors) => ...
case PartialParseSuccess(geometry, errors) => ...
}
我遇到了 ParseFailure:
List(MultipleMatchesError(/object/name), MultipleMatchesError(/object/truncated))
[错误][2]表示该路径匹配多个节点,而预期只有一个。 所以我想要的是获得一个 Seq[MyClass]。我如何告诉 XMLReader 我想将所有重复的标签解析为一个序列?我认为应用 .seq[T] 会做到这一点,但事实并非如此。 非常感谢您的帮助!
Upd.: 抱歉,我项目中的 xtract 版本确实是 2.2.1,而不是 2.2.0 我刚刚查看了 README 并希望在那里看到最新的版本号 [1]: https://github.com/lucidsoftware/xtract [2]: http://lucidsoftware.github.io/xtract/core/api/com/lucidchart/open/xtract/MultipleMatchesError.html
您的代码存在几个问题。路径 object/name
确实有歧义,因为你不知道你指的是第一个还是第二个。
首先,你需要定义一个包含所需序列的class,它的reader:
case class MyObjects(myObjects: Seq[MyObject])
object MyObjects {
implicit val reader: XmlReader[MyObjects] = (__ \ "object").read(seq[MyObject]).map(apply)
}
现在,由于此对象读取路径的 object
部分,我们需要从 MyObject
中省略该部分,这意味着它应该是:
case class MyObject(name: String, truncated: Boolean)
object MyObject {
implicit val xmlReader: XmlReader[MyObject] = (
(__ \ "name").read[String],
(__ \ "truncated").read[Boolean]
).mapN(MyObject.apply)
}
另一个问题是您将 truncated
解析为布尔值,但该值实际上是一个整数。所以我将 xml 更改为包含布尔值。
最后,为了阅读,我们可以这样做:
XmlReader.of[MyObjects].read(xml) match {
case ParseSuccess(seatsXml) => println(seatsXml)
case ParseFailure(errors) => println(errors)
case PartialParseSuccess(geometry, errors) => println(errors)
}
输出为:
MyObjects(Vector(MyObject(name1,false), MyObject(name2,true)))
代码 运行 在 Scastie。