【问题标题】:How to produce nicely formatted XML in Scala?如何在 Scala 中生成格式良好的 XML?
【发布时间】:2011-03-22 20:00:06
【问题描述】:

假设您定义了以下内容:

class Person(name: String, age: Int) {
    def toXml =
        <person>
            <name>{ name }</name>
            <age>{ age }</age>
        </person>   
}

val Persons = List(new Person("John", 34), new Person("Bob", 45))

然后生成一些 XML 并保存到文件中:

val personsXml = 
    <persons>
        { persons.map(_.toXml) }
    </persons>

scala.xml.XML.save("persons.xml", personsXml)

您最终会得到以下看起来很有趣的文字:

<persons>
        <person>
            <name>John</name>
            <age>32</age>
        </person><person>
            <name>Bob</name>
            <age>43</age>
        </person>
    </persons>

现在,当然,这是完全有效的 XML,但是如果您希望它在一个体面的文本编辑器中是人工可编辑的,那么 最好 将其格式设置得更好一些。

通过更改 Scala XML 文字各个点的缩进 - 使代码看起来 less 漂亮 - 可以生成上述输出的变体,但似乎不可能完全正确。我理解为什么它会变成这种格式,但想知道是否有任何方法可以解决它。

【问题讨论】:

    标签: scala


    【解决方案1】:

    您可以使用scala.xml.PrettyPrinter 对其进行格式化。遗憾的是,这不适用于大型文档,因为它只能格式化为 StringBuilder,并且不能直接写入流或写入器。

    【讨论】:

      【解决方案2】:

      我找不到使用 PrettyPrinter 并直接指定文件编码的方法。我发现的“解决方案”是这样的:

      val Encoding = "UTF-8"
      
      def save(node: Node, fileName: String) = {
      
          val pp = new PrettyPrinter(80, 2)
          val fos = new FileOutputStream(fileName)
          val writer = Channels.newWriter(fos.getChannel(), Encoding)
      
          try {
              writer.write("<?xml version='1.0' encoding='" + Encoding + "'?>\n")
              writer.write(pp.format(node))
          } finally {
              writer.close()
          }
      
          fileName
      }
      

      【讨论】:

        【解决方案3】:

        感谢“PrettyPrinter”的创意。这帮助很大。

        我发现了这种将 XML 元素写入具有适当缩进的文件的方法。

        val xmlData = // your xml here
        
        // max width: 80 chars
        // indent:     2 spaces
        val printer = new scala.xml.PrettyPrinter(80, 2)
        
        XML.save("yourFileName.xml", XML.loadString(printer.format(musicMarshaledXML)) , "UTF-8", true, null)
        

        非常感谢任何有关此实现的性能或任何缺点的反馈(使用“XML.save()”)

        【讨论】:

        • 这很好用。我使用 XML.write 对这种方法进行了改动,因此我可以指定目标目录。
        【解决方案4】:

        也许会有用。 使用文本编辑器时,尽量不要在 XML 代码中放置任何额外的选项卡,因为它们将保存在 xml 文件中。

        我的意思是,你的代码应该是这样的:

        val personsXml = 
        <persons>
           { persons.map(_.toXml) }
        </persons>
        

        而不是这个:

        val personsXml = 
            <persons>
                { persons.map(_.toXml) }
            </persons>
        

        它非常适合我。

        【讨论】:

          【解决方案5】:

          这是@Hel's 答案的模组,可以写入非本地目录的目标位置:

          val printer = new PrettyPrinter(80, 2)
          val targetFile = new java.io.File("./mytargetdir/file.xml")
          val prettyDoc = printer.format(document)
          val writer = new java.io.FileWriter(targetFile)
          scala.xml.XML.write(writer, XML.loadString(prettyDoc), "UTF-8", true, null)
          org.apache.commons.io.IOUtils.closeQuietly(writer);
          

          【讨论】:

            【解决方案6】:

            改编自DOMImplementationLS serialize to String in UTF-8 in JavaHow to pretty print XML from Java?

              def cleanXml(xml: String): String = {
                import org.w3c.dom.Node
                import org.w3c.dom.bootstrap.DOMImplementationRegistry
                import org.w3c.dom.ls.DOMImplementationLS
                import org.w3c.dom.ls.LSSerializer
                import org.xml.sax.InputSource
                import javax.xml.parsers.DocumentBuilderFactory
                import java.io.StringReader
                val src = new InputSource(new StringReader(xml))
                val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(src).getDocumentElement
                val keepDeclaration = java.lang.Boolean.valueOf(xml.startsWith("<?xml"))
                val registry = DOMImplementationRegistry.newInstance()
                val impl = registry.getDOMImplementation("LS").asInstanceOf[DOMImplementationLS]
                val lsOutput = impl.createLSOutput
                lsOutput.setEncoding("UTF-8")
                import java.io.StringWriter
                val stringWriter = new StringWriter
                lsOutput.setCharacterStream(stringWriter)
                val writer = impl.createLSSerializer()
                writer.getDomConfig.setParameter("format-pretty-print", true)
                writer.getDomConfig.setParameter("xml-declaration", keepDeclaration)
                writer.write(document, lsOutput)
                stringWriter.toString
              }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-06-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-10-06
              • 2016-02-01
              • 2016-11-10
              相关资源
              最近更新 更多