【问题标题】:Write non self closing tags XML in Scala在 Scala 中编写非自闭标签 XML
【发布时间】:2014-07-15 23:27:20
【问题描述】:

我有scala.xml.NodeSeq val,我需要将其写入文件。 我正在使用scala.XML.save 编写文件,但它正在生成带有自结束标签的 XML。我需要在不这样做的情况下编写它。 我的代码正在生成这样的 XML

<value key="attribute"/>

我需要这个

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

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

【问题讨论】:

  • 在 XML 中,这两种情况之间绝对没有语义差异。无论“需要”什么,后一种形式都应该是固定的。话虽如此,除非 scala.XML.save 具有可以为您执行此操作的功能,否则如果您坚持这样做,您将不得不找到另一个支持该选项的 XML 序列化程序...或将输出文档后处理成通过文本操作获得所需的形式。
  • 是的。但是由于某种原因读取此 XML 的烦人程序无法读取它...
  • 替换烦人的程序。严重地。如果它不能做到这一点,它将继续让你的生活变得悲惨,因为无法支持其他基本的 XML 行为。
  • 我别无选择。有问题的程序是 MySQL Workbench。我必须更改模型中的每个表。所以我打开了文件。读取它的 XML,更改它并再次保存。它只是不读取脚本的输出
  • 在这种情况下:找到另一个可以与您的 XML 模型一起使用并且具有您想要的行为的序列化程序(如果您使用 DOM 或 SAX 则容易,如果您使用其他东西则更难),或编写一个(不推荐;XML 序列化有一些丑陋的边缘情况,但您的数据可能足够简单,可以让您获得快速而肮脏的解决方案),或者采用 Desperate Perl Hacker 方法并后处理 XML 文本文件.

标签: xml scala


【解决方案1】:

嗯,

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

【讨论】:

【解决方案2】:

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

【讨论】:

    【解决方案3】:

    一种补救方法是修复 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
        })
      }    
    

    当用MinimizeMode.Default调用XML.write时,变换根元素:

      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")
    

    【讨论】:

      猜你喜欢
      • 2014-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-06
      • 2023-02-16
      相关资源
      最近更新 更多