如何在 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>
我有一个 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>