2010-07-29 64 views
20

說你定義如下:如何在Scala中生成格式良好的XML?

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文字的各個點的縮進 - 使代碼看起來更像不錯 - 可以生成上述輸出的變體,但似乎不可能讓它變得非常正確。我明白爲什麼它變成這種格式,但不知道是否有任何方法來解決它。

回答

21

您可以使用scala.xml.PrettyPrinter進行格式化。可悲的是,這不適用於大文件,因爲它只格式化爲StringBuilder,並且不直接寫入流或寫入器。

13

我找不到使用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 
} 
1

也許它會有用。 當您使用文本編輯器時,請不要在XML代碼中放置任何額外的選項卡,因爲它們將保存在xml文件中。

我的意思是,你的代碼應該是這樣的:

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

取而代之的是:

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

它完美地爲我工作。

2

感謝「漂亮打印機」的想法。這有很大幫助。

我發現這種方式可以將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()」)

+0

這個效果很好。我在這種方法上使用了XML.write,所以我可以指定目標目錄。 – 2017-08-11 23:54:55

0

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 
    } 
1

這是一個模到@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); 
相關問題