将带有名称空间和属性的复杂Scala XML转换为Scala对象

时间:2013-05-15 20:21:29

标签: xml scala xml-parsing xml-serialization

将普通的Scala XML转换为对象似乎很容易:

<object><field>1</field></object>可以使用带有Scala原生XML API的案例类Object(1)创建类似Object( field: Int )的内容。

但是如果XML包含名称空间和属性呢?比如ATOM格式?

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:service="http://activitystrea.ms/service-provider" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:georss="http://www.georss.org/georss" xmlns:gnip="http://www.gnip.com/schemas/2010">
<id>456520791711374025_380135597</id>
<published>2013-05-15T18:12:20Z</published>
<source>
<link rel="self" type="application/json" href="https://url.com/v1/tags/taghere/media/recent?client_id=xxxxxxxxxxx"/>
<updated>2013-05-15T18-12-43Z</updated>
<gnip:rule xmlns:gnip="http://www.gnip.com/schemas/2010">rulehere</gnip:rule>
</source>
<service:provider>
<name>Provider</name>
<uri>www.url.com</uri>
</service:provider>
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
<activity:object>
<activity:object-type>http://activitystrea.ms/schema/1.0/image</activity:object-type>
<gnip:statistics favoriteCount="0"/>
</activity:object>
</entry>

1 个答案:

答案 0 :(得分:0)

处理更复杂的XML格式需要对特定类进行高级注释。建议的策略是使用类似JAXB的内容来注释类中的每个字段。

以下是一些改编自http://krasserm.blogspot.ca/2012/02/using-jaxb-for-xml-and-json-apis-in.html的示例代码:

import scala.annotation.meta.field 

//Scala 2.9 or lower uses scala.annotation.target.field

import javax.xml.bind.annotation._
import javax.xml.bind.annotation.adapters._

type xmlElement     = XmlElement @field
type xmlTypeAdapter = XmlJavaTypeAdapter @field

class StringOptionAdapter extends OptionAdapter[String](null, "")
class OptionAdapter[A](nones: A*) extends XmlAdapter[A, Option[A]] {
  def marshal(v: Option[A]): A = v.getOrElse(nones(0))
  def unmarshal(v: A) = if (nones contains v) None else Some(v)
}

@XmlRootElement(name = "person")
@XmlAccessorType(XmlAccessType.FIELD)
case class Person(
    @xmlElement(required=true) fullname: String, 
    @xmlTypeAdapter(classOf[StringOptionAdapter]) username: Option[String], 
    age: Int) {
  // only needed and accessed by JAXB
  private def this() = this("", None, 0)
}

请注意,案例类要求您定位特定字段,因此导入annotation.meta.field

仅供参考,您可以在此处添加JAXB作为依赖项:http://search.maven.org/#artifactdetails%7Cjavax.xml.bind%7Cjaxb-api%7C2.2.9%7Cjar

修改

虽然我个人不喜欢它,但也可以通过scalaxb获得Xml支持。它作为本机插件工作,不一定充当典型的Maven依赖项。它使用XML模板等高级功能。