【问题标题】:Jerkson makes Scala JSON so easy, can it be the same for XML?Jerkson 让 Scala JSON 变得如此简单,XML 能一样吗?
【发布时间】:2012-03-20 16:20:31
【问题描述】:

诚然,我真的很喜欢 Jerkson 库,因为它使生成 JSON 变得如此简单。举个例子:

Json(generate(Job.search(parseDate(date),accountId)
      .map(job => Map("id" -> job.id,
      "name" -> job.name,
      "userId" -> job.userId.getOrElse("")
    ))))

但是我很难找到一个类似的库,它可以像这样轻松地生成和序列化 XML 节点等。是否有 Java 或 Scala 库可以以简单的语法生成节点和值,而无需制作“模板”或手动编写节点?

【问题讨论】:

  • 假设这样的库确实存在,给定您在示例中显示的Map,生成的 XML 会是什么?
  • 起初以为它可能看起来就像一个 RSS 提要。 <xml xmlns:a10="blah"><job><id>1</id><name>DeLonge</name></job><job>...</job></xml> 在这种情况下我并不担心属性,更多的是快速构建一个输出与 JSON API 相同数据的 API
  • 我一直在玩 Lift 的 Scala JSON 库……这看起来很有希望,尽管它可能更像是一种 hack,而不是一个干净的序列化……如果它转,我会发布一个答案成为一种干净的方法

标签: xml scala playframework


【解决方案1】:

由于属性和子节点的“双重层次”,构建 XML 比构建 JSON 困难得多。 JSON 结构很容易用标准 Scala 集合表示,通过嵌套映射和列表。

但如果您只对 XML 的一个子集感兴趣,那么问题就不那么复杂了。根据您对我的评论的回答,以下 sn-p 可能足以满足您的需要:

def tag( name: String, content: Seq[Node] ): Node =
  <xml></xml>.copy( label = name, child = content )

def toXML( label: String, content: String ): Node =
  tag( label, Text( content ) ) 

def toXML( root: String, map: Map[_,_] ): Node = {
  val children = for( (k,v) <- map ) yield {
    v match {
      case m: Map[_,_] => toXML( k.toString, m )
      case a => toXML(k.toString, a.toString )
    }
  }
  tag( root, children.toSeq )
}

它按预期工作。例如:

 val data = Map(
  "id" -> 121,
  "foo" -> Map(
    "hoo" -> "bar",
    "goo" -> "baz"
  )
)

val xml = convert.toXML( "example", data )

那么xml 将等于:

<example>
  <id>121</id>
  <foo>
    <hoo>bar</hoo>
    <goo>baz</goo>
  </foo>
</example>

这只是一个快速而肮脏的 hack,但我认为它可以很容易地改进(例如包括列表)并变得更安全。

【讨论】:

  • 它几乎看起来像是你自己的图书馆的开始;)我可能需要做一些调整(就像你说的......列表)但它有潜力。如果我有任何有用的改进,我会跟进,可惜这样的库还不存在。非常好!
【解决方案2】:

您知道 XML 是 Scala 中的原生类型吗?您可以直接返回 XML,不需要库。

有关示例,请参阅 this

【讨论】:

  • 等一下……真的那么简单吗?因此,如果我将上面示例中的地图插入 XML 节点,它只会将其全部序列化为 XML?我在这里错过了什么吗?
  • 是的,应该很简单。我不确定你想要哪个确切的输出,所以实现可能会略有不同,但正如你所见,你可以只输出 xml,所以...
  • 我会测试一下,我看到的最大问题是 scala 输出 html 实体的问题......不确定它会如何处理控制器对象的映射,但我们会看到......跨度>
  • 我不认为地图会被序列化为 XML... 它会被转换为字符串并包含为 XML 文本。
  • @paradigmatic 很好,没有样本很难,但是按照这个stackoverflow.com/questions/215767/… 它应该可以工作,不知何故
【解决方案3】:

您可以在 Scala 中使用 XML 内联:

val someNode = <root>
                   <child>
                       Some stuff goes here
                   </child>
               </root>

someNode \ "child" // returns the child node

someNode \ "child" text // returns the text of the child node

【讨论】:

    【解决方案4】:

    实际上有一个库可以做到这一点(只是不是通过 Scala Xml)——Scales Xml 提供了这种构建 DSL:

    val ns = Namespace("test:uri")
    val nsa = Namespace("test:uri:attribs")
    val nsp = nsa.prefixed("pre")
    
    val builder = 
      ns("Elem") /@ (nsa("pre", "attr1") -> "val1",
                   "attr2" -> "val2",
           nsp("attr3") -> "val3") /(
        ns("Child"),
        "Mixed Content",
        ns("Child2") /( ns("Subchild") ~> "text" )
      )
    

    here for more detailed documentation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-14
      • 1970-01-01
      • 2013-11-23
      • 2013-05-14
      • 1970-01-01
      • 2016-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多