【问题标题】:Scala: Convert org.w3c.dom.Document to scala.xml.NodeSeqScala:将 org.w3c.dom.Document 转换为 scala.xml.NodeSeq
【发布时间】:2011-04-24 17:49:38
【问题描述】:

标题是不言自明的。如何将 org.w3c.dom.Document 的实例转换为 Scala NodeSeq,以享受它的便利?

干杯
帕萨

【问题讨论】:

    标签: java xml dom scala


    【解决方案1】:
      def asXml(dom: org.w3c.dom.Node): Node = {
        val dom2sax = new DOM2SAX(dom)
        val adapter = new NoBindingFactoryAdapter
        dom2sax.setContentHandler(adapter)
        dom2sax.parse()
        return adapter.rootElem
      }
    

    【讨论】:

    • 这些问题要求从org.w3c.dom.Documentscala.xml.NodeSeq 的转换器,但您的代码将org.w3c.dom.Node 作为参数。 — 并且拥有适当的imports 总是会让事情变得容易一些。
    • 我找到了scala.xml.parsing.NoBindingFactoryAdapter,但我找不到DOM2SAX,因为没有钱。或者更好的谷歌返回很多结果,所以我不知道哪个是结果。 — 请:在示例代码中完全限定的类名。谢谢
    • 我猜你的意思是org.apache.xalan.xsltc.trax.DOM2SAX 这不仅意味着必须知道包名。还必须找出它在哪个外部库中。-剩下的一个:如何将org.w3c.dom.Document 转换为org.w3c.dom.Node
    • @Martin:由于org.w3c.dom.Document 扩展了org.w3c.dom.Node,您可以将Document 传递到此方法中。
    【解决方案2】:

    IttayD 的答案适用于所有 w3c XML - 除了 dom4j w3c 兼容的 xml。以下适用于所有 w3c 类型:

    def asXml(dom: _root_.org.w3c.dom.Node): Node = {
        val source = new DOMSource(dom)
        val adapter = new NoBindingFactoryAdapter
        val saxResult = new SAXResult(adapter)
        val transformerFactory = javax.xml.transform.TransformerFactory.newInstance()
        val transformer = transformerFactory.newTransformer()
        transformer.transform(source, saxResult)
        adapter.rootElem
      }
    

    【讨论】:

    • 我和 IttayD 说的一样:请:在示例代码中完全限定类名。谢谢。糟糕的是,javax.xml.transform.dom.DOMSource 在 Android API
    • 你的transformerFactory来自哪里?
    • @Jean-Philippe Pellet 在包含对象中定义了一个 val transformerFactory = javax.xml.transform.TransformerFactory.newInstance()。
    • 遗憾的是,我在尝试此操作时遇到错误:java.lang.AbstractMethodError: org.w3c.tidy.DOMDocumentImpl.getXmlStandalone()Z
    • 这适用于来自 Apache CXF jax-ws 生成的 SOAP 客户端的 SOAP 响应。如果上面是服务层范围内的implicit 函数,那就更方便了。上面返回的所有对象都是 scala.xml.Node.
    【解决方案3】:

    我之前写过这段代码,是为了朝另一个方向发展,从 Scala 节点到 Dom4J 节点。它展示了在树上递归的基本思想,应该很容易适应:

    implicit def scalaToDom4j(n : Node) : DElem = {
    
      def inner(n : Node) : Option[DNode] = {
        n match {
          case e : Elem =>
            val elem = DocumentHelper.createElement(e.label)
            for(c <- e.child) yield inner(c) collect {
              case Some(child) => elem.add(child)
            }
            Some(elem)
            //as Scala's xml is type-aware, text might not actually be a Text node,
            //but an Atom of some other type
          case t : Atom[_] =>
            Some(DocumentHelper.createText(t.data.toString))
          case x => None
        }
      }
    
      //Attempt the conversion. Throw an exception if something has gone badly wrong
      //inner returns an Option[DNode], but the expected top-level type is a DElem
      // (which is a subclass of DNode)
      //so we also validate this.
      inner(trim(n)) map (_.asInstanceOf[DElem]) getOrElse (error("xml failed"))
    }
    

    【讨论】:

      【解决方案4】:

      我有与上面的 scalaToDom4j(n) 函数类似的递归模式匹配代码,只是在 Saxon XdmNode 到 Scala 节点的方向上: https://github.com/LeifW/MusicPath/blob/master/src/main/scala/org/musicpath/saxon2scala/Saxon2Scala.scala

      目前它只制作文本、元素和非命名空间属性节点,但应该很容易概括/完成。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-08
        • 2014-04-27
        • 2016-11-24
        • 2019-10-20
        • 2018-06-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多