0

我有以下问题:我正在使用 [xtract][1],一个用于解析 XML 的 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>

这是我正在将 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

4

1 回答 1

1

您的代码有几个问题。路径object/name确实是模棱两可的,因为您不知道您是指第一个还是第二个。

首先,您需要定义一个包含所需序列的类及其阅读器:

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为布尔值,但该值实际上是一个 int。所以我将 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运行。

于 2020-11-22T22:40:54.860 回答