在Scala中编写非自闭项标记XML

时间:2014-07-15 23:27:20

标签: xml scala

我有scala.xml.NodeSeq val,我需要将其写入文件。 我正在使用scala.XML.save来编写文件,但它正在生成带有自闭标签的XML。我不需要这样做就能写出来。 我的代码正在生成像这样的XML

<value key="attribute"/>

我需要这个

<value key="attribute"></value>

我还尝试使用scala.XML.write方法将最后一个参数作为MinimizeMode.Never传递,但它也生成了带有自闭标签的XML。 你知道有什么方法可以避免这种行为吗?

3 个答案:

答案 0 :(得分:4)

那么,

scala> val x = <value key="attr"></value>
x: scala.xml.Elem = <value key="attr"></value>

scala> x.min
min   minBy   minimizeEmpty

scala> x.minimizeEmpty
res0: Boolean = false

scala> val x = <value key="attr"/>
x: scala.xml.Elem = <value key="attr"/>

scala> x.minimizeEmpty
res1: Boolean = true

scala> val pw = new java.io.PrintWriter(Console.out)
pw: java.io.PrintWriter = java.io.PrintWriter@2b50150

scala> xml.XML.write(pw, x, "", false, null)

scala> pw.flush
<value key="attr"/>
scala> val x = <value key="attr"></value>
x: scala.xml.Elem = <value key="attr"></value>

scala> xml.XML.write(pw, x, "", false, null) ; pw.flush()
<value key="attr"></value>
scala> val x = <value key="attr"/>
x: scala.xml.Elem = <value key="attr"/>

scala> xml.XML.write(pw, x, "", false, null) ; pw.flush()
<value key="attr"/>
scala> xml.XML.write(pw, x, "", false, null, xml.MinimizeMode.Never) ; pw.flush()
<value key="attr"></value>

除了Elem之外还有NodeSeq,显然:

scala> val n: NodeSeq = new xml.Unparsed("""<value key="attr"/>""")
n: scala.xml.NodeSeq = <value key="attr"/>

scala> xml.XML.write(pw, n.head, "", false, null, xml.MinimizeMode.Never) ; pw.flush()
<value key="attr"/>
scala> 

显示OP指出的错误:

$ scala
Welcome to Scala version 2.11.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import xml._
import xml._

scala> val pw = new java.io.PrintWriter(Console.out)
pw: java.io.PrintWriter = java.io.PrintWriter@17d99928

scala> val x = <value key="attr"><value key="another"/></value>
x: scala.xml.Elem = <value key="attr"><value key="another"/></value>

scala> xml.XML.write(pw, x, "", false, null, xml.MinimizeMode.Never) ; pw.flush()
<value key="attr"><value key="another"/></value>
scala> 

https://github.com/scala/scala-xml/blob/master/src/main/scala/scala/xml/Utility.scala#L237

编辑,在2.12中显示固定:

$ scala
Welcome to Scala 2.12.3 (OpenJDK 64-Bit Server VM, Java 1.8.0_131).
Type in expressions for evaluation. Or try :help.

scala> import xml._
import xml._

scala> val pw = new java.io.PrintWriter(Console.out)
pw: java.io.PrintWriter = java.io.PrintWriter@1a256d80

scala> val x = <value key="attr"><value key="another"/></value>
x: scala.xml.Elem = <value key="attr"><value key="another"/></value>

scala> xml.XML.write(pw, x, "", false, null, xml.MinimizeMode.Never) ; pw.flush()
<value key="attr"><value key="another"></value></value>
scala>

https://github.com/scala/scala-xml/commit/b696beaa481a11a5276186b9e2bc2be3cb32a922

答案 1 :(得分:0)

我设法解决了旧版scala中运行的问题。在这里找到答案:Forcing Scala's XML library to render "singleton tag" (e.g., <br/>) as such

答案 2 :(得分:0)

一种补救方法是修复XML树,显式设置每个元素的minimizeEmpty属性。

  def fixSelfClosing(nodes: Seq[Node], minimize: Set[String]) : Seq[Node] = {    
    nodes.map(n => n match {
      case e: Elem => e.copy(child = fixSelfClosing(e.child, minimize),
        minimizeEmpty = minimize.contains(e.label))
      case _ => n
    })
  }    

XML.write调用MinimizeMode.Default时,请转换根元素:

  XML.write(pw, fixSelfClosing(Seq(rootElement), minimizedTags)(0),
    xmlDecl = false, doctype = null, 
    minimizeTags = MinimizeMode.Default)

其中minimizedTags是要自动关闭的标签集。例如,使用XHTML:

  val minimizedTags = Set("area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr")