如何在 Scala 中将地图转换为节点?

How to convert map to node in Scala?

我有一个 Map[String,List[String]] 类型的数据,想在 Scala 中保存为 xml 文件。如果我选择使用 scala.xml.XML.save 方法,我需要将地图转换为节点。

但是我没有找到方法。而且好像map和node库都没有方法可以做到。

您必须手动创建转换器,因为 xml 彼此可能完全不同,这是您可以使用的示例。

import scala.xml.{Node, NodeSeq}

val a:Map[String, List[String]] = Map("animal" -> List("cat", "dog", "bird"), "fruit" -> List("banana", "apple"))

def convertToXML(parametersToCreateXML: Map[String,List[String]]): NodeSeq = {
  def generateTitleToData(keyValue: (String, List[String])): Node = {
    <member>
      <name>{keyValue._1}</name>
      <values>
        {keyValue._2.map(x =>generateData(x))}
      </values>
    </member>
  }

  def generateData(value: String): Node = {
    <value>
      <string>{value}</string>
    </value>
  }

  parametersToCreateXML.map(x => generateTitleToData(x)).toSeq
}

convertToXML(a)

res0: scala.xml.NodeSeq =
NodeSeq(<member>
      <name>animal</name>
      <values>
        <value>
      <string>cat</string>
    </value><value>
      <string>dog</string>
    </value><value>
      <string>bird</string>
    </value>
      </values>
    </member>, <member>
      <name>fruit</name>
      <values>
        <value>
      <string>banana</string>
    </value><value>
      <string>apple</string>
    </value>
      </values>
    </member>)

如您所见,从 Seq[Node]NodeSeq 的转换是隐式完成的。

您也可以尝试下一个库:https://github.com/mthaler/xmlconfect - 与其他编解码器库(例如 circe、Play Json 等)类似的想法 - 它通过隐式基于类型构建编解码器。 在您的情况下,它看起来像下一个:

import scala.xml.PrettyPrinter
import com.mthaler.xmlconfect._
import com.mthaler.xmlconfect.ProductFormatInstances._
import com.mthaler.xmlconfect.BasicTextFormats._
import com.mthaler.xmlconfect.CollectionFormats._

object XmlFormat {
  type RawData = Map[String, List[String]]

  case class TypedDataElement(item: String)

  object TypedDataElement {
    implicit val format: XmlElemFormat[TypedDataElement] = xmlFormat1(TypedDataElement.apply)
  }

  case class TypedDataNode(key: String, item: List[TypedDataElement])

  object TypedDataNode {
    implicit val format: XmlElemFormat[TypedDataNode] = xmlFormat2(TypedDataNode.apply)
  }

  case class AllTypedData(data: List[TypedDataNode]) {
    def toRawData: RawData = {
      data.map(item => item.key -> item.item.map(_.item)).toMap
    }
  }

  object AllTypedData {
    implicit val format: XmlElemFormat[AllTypedData] = xmlFormat1(AllTypedData.apply)

    def fromRaw(raw: RawData): AllTypedData = {
      val all = raw.toList.map {
        case (key, values) =>  TypedDataNode(key, values.map(TypedDataElement.apply))
      }
      AllTypedData(all)
    }
  }

  def main(args: Array[String]): Unit = {
    val rawData: RawData = Map("node" -> List("value1", "value2"))
    val typedData = AllTypedData.fromRaw(rawData)
    val printer = new PrettyPrinter(80, 4)
    println(printer.formatNodes(typedData.toNode))
  }
}

案例 类 的引入是为了提供密钥名称。

在这种特殊情况下的结果输出将是:

<AllTypedData>
    <TypedDataNode>
        node
        <TypedDataElement>value1</TypedDataElement>
        <TypedDataElement>value2</TypedDataElement>
    </TypedDataNode>
</AllTypedData>