如何在 Scala 中生成格式良好的 XML?

Posted

技术标签:

【中文标题】如何在 Scala 中生成格式良好的 XML?【英文标题】:How to produce nicely formatted XML in Scala? 【发布时间】: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 漂亮 - 可以生成上述输出的变体,但似乎不可能完全正确。我理解为什么它会变成这种格式,但想知道是否有任何方法可以解决它。

【问题讨论】:

【参考方案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 Java和How 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
  

【讨论】:

以上是关于如何在 Scala 中生成格式良好的 XML?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 scala 中生成的键值对中添加值

如何从数据库表中生成xml文件?

如何在 Oracle 中生成 xml 空值?

如何在xml中生成schema约束

如何在未绑定的 xml 结构中生成逗号分隔的字符串

如何在 C# 中生成时间和日期并为 mysql 格式化?