Подтвердить что ты не робот

Как создать красиво отформатированный XML в Scala?

Предположим, вы определили следующее:

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, но если вы хотите, чтобы он был редактируемым человеком в достойном текстовом редакторе, было бы предпочтительнее отформатировать его немного красивее.

Изменяя отступы в разных точках XML-литералов Scala, делая код менее привлекательным, можно генерировать вариации вышеприведенного вывода, но кажется, что это невозможно. Я понимаю, почему он форматируется таким образом, но задайтесь вопросом, есть ли способы обойти его.

4b9b3361

Ответ 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()" )

Ответ 4

Может быть, это будет полезно. Когда вы используете текстовый редактор, попробуйте не добавлять дополнительные вкладки в код XML, потому что они будут сохранены в XML файле.

Я имею в виду, что ваш код должен выглядеть следующим образом:

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

Вместо этого:

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

Это отлично сработало для меня.

Ответ 5

это мода на @answer, который может писать в целевое местоположение, которое не является локальным каталогом:

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 сериализуется в String в UTF-8 в Java и Как довольно печатать XML с 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
  }