2016-09-13 17 views
-2

我知道類似這個問題的東西已經被問過很多次了,並且我已經嘗試了很多的建議,但由於某種原因,我無法得到這個工作。簡單的方法來獲得對Java中的字符串執行Xpath?

我在一個String變量中有一個XML文檔(在「compositeBodyLine」中),我想對該XML文檔執行Xpath搜索並從該Xpath搜索中獲得結果。

我該怎麼做?

這裏是什麼,我已經試過(或實際上將幾個不同的東西,我發現一個例子:

// From: http://javarevisited.blogspot.com/2012/12/create-and-evaluate-xpath-java-example-tutorial-program.html 

    //Create DocumentBuilderFactory for reading xml file 
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    DocumentBuilder builder = factory.newDocumentBuilder(); 

    InputStream inputStream = new ByteArrayInputStream(compositeBodyLine.getBytes()); 
    org.w3c.dom.Document doc = builder.parse(inputStream); 

    System.out.println("doc.getParentNode()=[" + doc.getParentNode().toString() + "]"); 

    // Create XPathFactory for creating XPath Object 
    XPathFactory xPathFactory = XPathFactory.newInstance(); 

    // Create XPath object from XPathFactory 
    XPath xpath = xPathFactory.newXPath(); 

    // Compile the XPath expression for getting all brands 
    XPathExpression xPathExpr = xpath.compile("/soapEnv:Envelope"); 

    // XPath text example : executing xpath expression in java 
    Object result = xPathExpr.evaluate(doc, XPathConstants.NODESET); 
    System.out.println("Java Xpath text example: All brands of popular smartphones "); 

    printXpathResult(result); 

. 
. 
. 
. 
public static org.w3c.dom.Document loadXMLFromString(String xml) throws Exception 
{ 
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    DocumentBuilder builder = factory.newDocumentBuilder(); 
    InputSource is = new InputSource(new StringReader(xml)); 
    return builder.parse(is); 
} 

當我嘗試上面的代碼,我得到空回來時,我認爲大多數的我看過的示例以文件作爲輸入,而在我的情況下,我將XML文檔放在字符串變量中,所以如果我必須猜測,我會猜測在輸入XML輸入時遇到問題。

有人可以提供一個簡單的方法來完成這個嗎?

個謝謝, 吉姆

編輯:下面是輸入XML的例子:你對XML

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <soapenv:Body> 
     <Request xmlns:xacml-context="urn:oasis:names:tc:xacml:2.0:context:schema:os" xmlns:ns9="urn:oasis:xacml:2.0:saml:assertion:schema:os" xmlns:ns8="urn:oasis:xacml:2.0:saml:protocol:schema:os" xmlns:ns7="http://security.bea.com/ssmws/ssm-soap-types-1.0.xsd" xmlns:ns6="http://www.w3.org/2001/04/xmlenc#" xmlns:ns5="urn:oasis:names:tc:xacml:2.0:policy:schema:os" xmlns:ns4="urn:oasis:names:tc:xacml:2.0:context:schema:os" xmlns:ns3="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns="urn:oasis:names:tc:xacml:2.0:context:schema:os"> 
      <Subject> 
       <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" DataType="http://security.bea.com/ssmws/ssm-ws-1.0.wsdl#OESPrincipalInfo"> 

        <AttributeValue>{name=jimXXXX1234}+(class=weblogic.security.principal.WLSUserImpl)</AttributeValue> 
       </Attribute> 
<!-- FOLLOWING IS **THE** GOOD WAY AND DOES WORK WITH OES FOR ROLE --> 
<Attribute AttributeId="http://oracle.com/symbols/oes/attribute/group-assertion" DataType="http://security.bea.com/ssmws/ssm-ws-1.0.wsdl#OESPrincipalInfo" xsi:type="ns1:AttributeType"> 
<AttributeValue xsi:type="ns1:AttributeValueType">{name=Operators}+(class=weblogic.security.principal.WLSGroupImpl)</AttributeValue> 
</Attribute> 
      </Subject> 
      <Resource> 
       <Attribute AttributeId="urn:oasis:names:tc:xacml:2.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string"> 
        <AttributeValue>foo/foo1/foo2</AttributeValue> 
       </Attribute> 
      </Resource> 
      <Action> 
       <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" DataType="http://www.w3.org/2001/XMLSchema#string"> 
        <AttributeValue>GET</AttributeValue> 
       </Attribute> 
      </Action> 
<ns4:Environment xsi:type="ns4:EnvironmentType" 
    xmlns:ns4="urn:oasis:names:tc:xacml:2.0:context:schema:os" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <ns4:Attribute AttributeId="http://security.bea.com/ssmws/ssm-ws-1.0.wsdl#RegisteredAttribute" 
    DataType="http://www.w3.org/2001/XMLSchema#string" xsi:type="ns4:AttributeType"> 
    <ns4:AttributeValue xsi:type="ns4:AttributeValueType">4444444444yes</ns4:AttributeValue> 
    </ns4:Attribute> 
    <ns4:Attribute AttributeId="http://security.bea.com/ssmws/ssm-ws-1.0.wsdl#NumberOfBorrowedBooksAttribute" 
     DataType="http://www.w3.org/2001/XMLSchema#string" xsi:type="ns4:AttributeType"> 
     <ns4:AttributeValue xsi:type="ns4:AttributeValueType">abc</ns4:AttributeValue> 
    </ns4:Attribute> 
</ns4:Environment> 
        </Request> 
    </soapenv:Body> 
</soapenv:Envelope> 
+2

不要使用'String.getBytes()'字節數組發送到DOM解析器。字符串本身:'builder.parse(new InputSource(new StringReader(compositeBodyLine)))'。 ---你有'loadXMLFromString()'方法這樣做,所以你爲什麼不使用它? – Andreas

+1

您的XPath表達式使用的是名稱空間前綴('soapEnv:'),但* 1)*您沒有定義該前綴(調用'xpath.setNamespaceContext(...)'來解決這個問題),* 2)*你沒有使用命名空間解析文檔(調用'factory.setNamespaceAware(true)'來解決這個問題)。 ---除此之外,當我們不知道XML是什麼樣的時候,你如何期待我們提供幫助? – Andreas

+0

Andreas - 我在原始msg中添加了一個XML示例。另外我嘗試了關於builder.parse(new InputSource(new StringReader(compositeBodyLine)))的建議,但是我得到了一個N​​ullPointerException。 – user555303

回答

1

史蒂夫,其中的原因可能是命名空間。解決這個問題的一種方法是註冊名稱空間。更簡單的方法可以是使用本地名稱。您的程序的較短版本如下所示,它會按預期返回一個節點集。我創建了一個最小的測試程序,在這裏,請讓我知道,如果這個工程對於其他XPATH你可能有

import java.io.ByteArrayInputStream; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.xpath.XPath; 
import javax.xml.xpath.XPathConstants; 
import javax.xml.xpath.XPathExpression; 
import javax.xml.xpath.XPathFactory; 

import org.w3c.dom.Document; 

public class XPathClass { 
    public static void main(String[] args) throws Exception { 
     String soapXML = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> <soapenv:Body>  <Request xmlns:xacml-context=\"urn:oasis:names:tc:xacml:2.0:context:schema:os\" xmlns:ns9=\"urn:oasis:xacml:2.0:saml:assertion:schema:os\" xmlns:ns8=\"urn:oasis:xacml:2.0:saml:protocol:schema:os\" xmlns:ns7=\"http://security.bea.com/ssmws/ssm-soap-types-1.0.xsd\" xmlns:ns6=\"http://www.w3.org/2001/04/xmlenc#\" xmlns:ns5=\"urn:oasis:names:tc:xacml:2.0:policy:schema:os\" xmlns:ns4=\"urn:oasis:names:tc:xacml:2.0:context:schema:os\" xmlns:ns3=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:ns2=\"http://www.w3.org/2000/09/xmldsig#\" xmlns=\"urn:oasis:names:tc:xacml:2.0:context:schema:os\">   <Subject>    <Attribute AttributeId=\"urn:oasis:names:tc:xacml:1.0:subject:subject-id\" DataType=\"http://security.bea.com/ssmws/ssm-ws-1.0.wsdl#OESPrincipalInfo\">     <AttributeValue>{name=jimlum1234}+(class=weblogic.security.principal.WLSUserImpl)</AttributeValue>    </Attribute><!-- FOLLOWING IS **THE** GOOD WAY AND DOES WORK WITH OES FOR ROLE --><Attribute AttributeId=\"http://oracle.com/symbols/oes/attribute/group-assertion\" DataType=\"http://security.bea.com/ssmws/ssm-ws-1.0.wsdl#OESPrincipalInfo\" xsi:type=\"ns1:AttributeType\"> <AttributeValue xsi:type=\"ns1:AttributeValueType\">{name=Operators}+(class=weblogic.security.principal.WLSGroupImpl)</AttributeValue> </Attribute>    </Subject>   <Resource>    <Attribute AttributeId=\"urn:oasis:names:tc:xacml:2.0:resource:resource-id\" DataType=\"http://www.w3.org/2001/XMLSchema#string\">     <AttributeValue>foo/foo1/foo2</AttributeValue>    </Attribute>   </Resource>   <Action>    <Attribute AttributeId=\"urn:oasis:names:tc:xacml:1.0:action:action-id\" DataType=\"http://www.w3.org/2001/XMLSchema#string\">     <AttributeValue>GET</AttributeValue>    </Attribute>   </Action><ns4:Environment xsi:type=\"ns4:EnvironmentType\"  xmlns:ns4=\"urn:oasis:names:tc:xacml:2.0:context:schema:os\"  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> <ns4:Attribute AttributeId=\"http://security.bea.com/ssmws/ssm-ws-1.0.wsdl#RegisteredAttribute\"  DataType=\"http://www.w3.org/2001/XMLSchema#string\" xsi:type=\"ns4:AttributeType\"> <ns4:AttributeValue xsi:type=\"ns4:AttributeValueType\">4444444444yes</ns4:AttributeValue> </ns4:Attribute> <ns4:Attribute AttributeId=\"http://security.bea.com/ssmws/ssm-ws-1.0.wsdl#NumberOfBorrowedBooksAttribute\"  DataType=\"http://www.w3.org/2001/XMLSchema#string\" xsi:type=\"ns4:AttributeType\">  <ns4:AttributeValue xsi:type=\"ns4:AttributeValueType\">abc</ns4:AttributeValue> </ns4:Attribute></ns4:Environment>     </Request> </soapenv:Body></soapenv:Envelope>"; 
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder builder = factory.newDocumentBuilder(); 
     Document doc = builder.parse(new ByteArrayInputStream(soapXML.getBytes())); 

     XPathFactory xPathFactory = XPathFactory.newInstance(); 

     // Create XPath object from XPathFactory 
     XPath xpath = xPathFactory.newXPath(); 

     // Compile the XPath expression for getting all brands 
     XPathExpression xPathEnvelopeExpr = xpath.compile("//*[local-name()='Envelope']"); 
     Object result = xPathEnvelopeExpr.evaluate(doc, XPathConstants.NODESET); 
     System.out.println("Java Xpath text example: All brands of popular smartphones " + result); 

    } 

} 
+0

Ramachandran GA - 我認爲接近我需要的工作,但是,僅供參考,我從我發佈的代碼添加了「printXpathResult()」方法,稍作修改以輸出節點值和名稱,它顯示節點名稱都是正確的,但節點值(nodes.item(i).getNodeValue())返回爲空值。 – user555303

+0

Ramachandran G A - 好的,我能夠得到這些值。我曾經使用「nodes.item(i).getTextContent()」而不是「nodes.item(i).getNoteValue()」。謝謝!! – user555303

相關問題