XPath 命名空间绑定在将其构建为文档后丢失

XPath namepsace binding is lost after building it as document

我正在尝试对 xml 格式的字符串进行 Xpath 查询。使用 javax.xml 库

这是我的代码(这段代码可能看起来很奇怪,因为我使用的是 scala。我将 java 代码转换为 scala 代码):

    import javax.xml.xpath._
  import org.xml.sax.InputSource
  import java.io.StringReader
  import javax.xml.parsers._
  import javax.xml.transform.dom.DOMSource
  import java.io.StringWriter
  import javax.xml.transform.stream.StreamResult
  import javax.xml.transform.TransformerFactory
  import javax.xml.namespace.NamespaceContext
  import java.io.ByteArrayInputStream
  import org.w3c.dom._
  import java.util.Iterator
  import javax.xml._
  import org.apache.ws.commons.util.NamespaceContextImpl


   val sampleXML = """<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
      <soap:Body>
        <ns2:CreateTransactionResponse xmlns:ns2="http://testing.xml.ph/provisioning/1">
          <status>404</status>
          <reason>not found</reason>
        </ns2:CreateTransactionResponse>
      </soap:Body>
    </soap:Envelope>"""


   val inputSource = new InputSource(new StringReader(sampleXML))


   var personalNameSpace = new NamespaceContextImpl
   personalNameSpace.startPrefixMapping("soap", "http://schemas.xmlsoap.org/soap/envelope/")
   personalNameSpace.startPrefixMapping("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/")
   personalNameSpace.startPrefixMapping("ns2", "http://testing.xml.ph/provisioning/1")

   var factory = XPathFactory.newInstance()
   var xpath = factory.newXPath()

   xpath.setNamespaceContext(personalNameSpace)

   //To check whether or not the namespace is properly binded in the xpath. 
   //And it is. This one returns "PREFIX : SOAP-ENV"
   println("PREFIX : " + xpath.getNamespaceContext.getPrefix("http://schemas.xmlsoap.org/soap/envelope/"))


   var dbf = DocumentBuilderFactory.newInstance()
   var docbuild = dbf.newDocumentBuilder()
   var document = docbuild.parse(inputSource)


   val testExtract = xpath.evaluate("/*[local-name() = 'Envelope']/soap:Body", document, XPathConstants.NODESET).asInstanceOf[NodeList]

   println(s"testExtractSize : ${testExtract.getLength}") // Returns 0

   for(index <- 0 until testExtract.getLength) {
     val node = testExtract.item(index)
     println(s"Node Text Content: ${node.getTextContent}")
     println(s"Node LocalName: ${node.getLocalName}")
     println(s"Node Prefix: ${node.getPrefix}")
   }

但是当我不将其更改为文档而只是在我的 xpath 中使用 inputSource 时。它正确 returns 我需要的一切 :

val testExtract = xpath.evaluate("/*[local-name() = 'Envelope']/soap:Body", inputSource, XPathConstants.NODESET).asInstanceOf[NodeList]

我得到了正确的日志:

Node Text Content: 

          404
          not found


Node LocalName: Body
Node Prefix: soap

为什么要改成文档?因为我需要重用它。而 InputSource 不会这样做。我需要重新初始化它。

此致

确保你做到了

var dbf = DocumentBuilderFactory.newInstance()
dbf.setNamespaceAware(true);

在对 DOM 文档进行任何 XSLT/XPath 操作之前。