- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我正在使用 scala 通过 scala.xml.XML.loadFile()
方法从文件加载 XML 文件。我正在使用的文档已经定义了 namespace ,我希望使用 scala 将 namespace 更改为其他名称。例如,文档的 xmlns 为“http://foo.com/a”,前缀为“a”- 我想将文档的命名空间和前缀分别更改为“http://foo.com/b”和“b”。
看起来很简单,我觉得我在这里遗漏了一些明显的东西。从引用的 loadFile()
方法返回的 Elem
获取命名空间没有问题。
最佳答案
在这里。由于 NamespaceBinding 是嵌套的(每个 ns 都有一个父级,TopScope 除外),我们需要递归来修复它。此外,每个 ns 都有一个 URI 和一个前缀,我们需要更改两者。
下面的函数将只更改一个特定的 URI 和前缀,它会检查所有命名空间,以查看前缀或 URI 是否需要更改。它将更改彼此独立的前缀或 URI,这可能不是我们想要的。不过,解决这个问题没什么大不了的。
至于其余部分,只需对 Elem 进行模式匹配以递归到 XML 的每个部分。啊,是的,它也改变了元素的前缀。同样,如果这不是我们想要的,也很容易改变。
代码假设没有必要递归到 XML 的“其他”部分——其余部分通常是文本元素。此外,它假定其他地方没有 namespace 。我不是 XML 方面的专家,所以我在这两个方面都可能是错误的。再说一次,改变它应该很容易——只需遵循模式即可。
def changeNS(el: Elem,
oldURI: String, newURI: String,
oldPrefix: String, newPrefix: String): Elem = {
def replace(what: String, before: String, after: String): String =
if (what == before) after else what
def fixScope(ns: NamespaceBinding): NamespaceBinding =
if(ns == TopScope)
TopScope
else new NamespaceBinding(replace(ns.prefix, oldPrefix, newPrefix),
replace(ns.uri, oldURI, newURI),
fixScope(ns.parent))
def fixSeq(ns: Seq[Node]): Seq[Node] = for(node <- ns) yield node match {
case Elem(prefix, label, attribs, scope, children @ _*) =>
Elem(replace(prefix, oldPrefix, newPrefix),
label,
attribs,
fixScope(scope),
fixSeq(children) : _*)
case other => other
}
fixSeq(el.theSeq)(0).asInstanceOf[Elem]
}
但这会产生意想不到的结果。范围被添加到所有元素。那是因为 NamespaceBinding 没有定义 equals 方法,因此使用引用相等。我已经给它开票了,2138 , 已经关闭,所以 Scala 2.8 不会有这个问题。
同时,以下代码将正常工作。它保留命名空间缓存。它还在处理之前将 NamespaceBinding 分解为一个列表。
def changeNS(el: Elem,
oldURI: String, newURI: String,
oldPrefix: String, newPrefix: String): Elem = {
val namespaces = scala.collection.mutable.Map.empty[List[(String, String)],NamespaceBinding]
def replace(what: String, before: String, after: String): String =
if (what == before) after else what
def unfoldNS(ns: NamespaceBinding): List[(String, String)] = ns match {
case TopScope => Nil
case _ => (ns.prefix, ns.uri) :: unfoldNS(ns.parent)
}
def foldNS(unfoldedNS: List[(String, String)]): NamespaceBinding = unfoldedNS match {
case knownNS if namespaces.isDefinedAt(knownNS) => namespaces(knownNS)
case (prefix, uri) :: tail =>
val newNS = new NamespaceBinding(prefix, uri, foldNS(tail))
namespaces(unfoldedNS) = newNS
newNS
case Nil => TopScope
}
def fixScope(ns: NamespaceBinding): NamespaceBinding =
if(ns == TopScope)
ns
else {
val unfoldedNS = unfoldNS(ns)
val fixedNS = for((prefix, uri) <- unfoldedNS)
yield (replace(prefix, oldPrefix, newPrefix), replace(uri, oldURI, newURI))
if(!namespaces.isDefinedAt(unfoldedNS))
namespaces(unfoldedNS) = ns // Save for future use
if(fixedNS == unfoldedNS)
ns
else
foldNS(fixedNS)
}
def fixSeq(ns: Seq[Node]): Seq[Node] = for(node <- ns) yield node match {
case Elem(prefix, label, attribs, scope, children @ _*) =>
Elem(replace(prefix, oldPrefix, newPrefix),
label,
attribs,
fixScope(scope),
fixSeq(children) : _*)
case other => other
}
fixSeq(el.theSeq)(0).asInstanceOf[Elem]
}
关于xml - 使用 Scala 更改 XML 命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1094600/
我有一些 Scala 代码,它用两个不同版本的类型参数化函数做了一些漂亮的事情。我已经从我的应用程序中简化了很多,但最后我的代码充满了形式 w(f[Int],f[Double]) 的调用。哪里w()是
如果我在同一目录中有两个单独的未编译的 scala 文件: // hello.scala object hello { def world() = println("hello world") }
val schema = df.schema val x = df.flatMap(r => (0 until schema.length).map { idx => ((idx, r.g
环境: Play 2.3.0/Scala 2.11.1/IntelliJ 13.1 我使用 Typesafe Activator 1.2.1 用 Scala 2.11.1 创建一个新项目。项目创建好后
我只是想知道如何使用我自己的类扩展 Scala 控制台和“脚本”运行程序,以便我可以通过使用实际的 Scala 语言与其通信来实际使用我的代码?我应将 jar 放在哪里,以便无需临时配置即可从每个 S
我已经根据 README.md 文件安装了 ensime,但是,我在低级 ensime-server 缓冲区中出现以下错误: 信息: fatal error :scala.tools.nsc.Miss
我正在阅读《Scala 编程》一书。在书中,它说“一个函数文字被编译成一个类,当在运行时实例化时它是一个函数值”。并且它提到“函数值是对象,因此您可以根据需要将它们存储在变量中”。 所以我尝试检查函数
我有 hello world scala native 应用程序,想对此应用程序运行小型 scala 测试我使用通常的测试命令,但它抛出异常: NativeMain.scala object Nati
有few resources在网络上,在编写与代码模式匹配的 Scala 编译器插件方面很有指导意义,但这些对生成代码(构建符号树)没有帮助。我应该从哪里开始弄清楚如何做到这一点? (如果有比手动构建
我是 Scala 的新手。但是,我用 创建了一个中等大小的程序。斯卡拉 2.9.0 .现在我想使用一个仅适用于 的开源库斯卡拉 2.7.7 . 是吗可能 在我的 Scala 2.9.0 程序中使用这个
有没有办法在 Scala 2.11 中使用 scala-pickling? 我在 sonatype 存储库中尝试了唯一的 scala-pickling_2.11 工件,但它似乎不起作用。我收到消息:
这与命令行编译器选项无关。如何以编程方式获取代码内的 Scala 版本? 或者,Eclipse Scala 插件 v2 在哪里存储 scalac 的路径? 最佳答案 这无需访问 scala-compi
我正在阅读《Scala 编程》一书,并在第 6 章中的类 Rational 实现中遇到了一些问题。 这是我的 Rational 类的初始版本(基于本书) class Rational(numerato
我是 Scala 新手,我正在尝试开发一个使用自定义库的小项目。我在库内创建了一个mysql连接池。这是我的库的build.sbt organization := "com.learn" name :
我正在尝试运行一些 Scala 代码,只是暂时打印出“Hello”,但我希望在 SBT 项目中编译 Scala 代码之前运行 Scala 代码。我发现在 build.sbt 中有以下工作。 compi
Here链接到 maven Scala 插件使用。但没有提到它使用的究竟是什么 Scala 版本。我创建了具有以下配置的 Maven Scala 项目: org.scala-tools
我对 Scala 还很陌生,请多多包涵。我有一堆包裹在一个大数组中的 future 。 future 已经完成了查看几 TB 数据的辛勤工作,在我的应用程序结束时,我想总结上述 future 的所有结
我有一个 scala 宏,它依赖于通过包含其位置的静态字符串指定的任意 xml 文件。 def myMacro(path: String) = macro myMacroImpl def myMacr
这是我的功能: def sumOfSquaresOfOdd(in: Seq[Int]): Int = { in.filter(_%2==1).map(_*_).reduce(_+_) } 为什么我
这个问题在这里已经有了答案: Calculating the difference between two Java date instances (45 个答案) 关闭 5 年前。 所以我有一个这
我是一名优秀的程序员,十分优秀!