2016-09-13 4 views
-2

Я знаю, что что-то похожее на этот вопрос задавали (и отвечали) несколько раз, и я пробовал много предложений, но по какой-то причине я не могу заставить эту работу работать.Простой способ получить выполнение Xpath против строки в Java?

У меня есть XML-документ (в составной составной строке) в переменной String, и я хочу выполнить поиск по Xpath в этом документе XML и получить результат (ы) из этого поиска в 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-документ в переменной String, поэтому, если бы я должен был догадаться, я бы предположил, что у меня возникают проблемы с вводом XML-данных.

Может ли кто-нибудь предоставить простой способ для этого?

Спасибо, Jim

EDIT: Вот пример входного 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 (новый InputSource (новый StringReader (compositeBodyLine))). --- У вас есть 'loadXMLFromString()' метод, делающий это таким образом, так почему бы вам не использовать его ???? – Andreas

+1

Ваше выражение XPath использует префикс пространства имен ('soapEnv:'), но * 1) * вы не определили этот префикс (вызовите 'xpath.setNamespaceContext (...)', чтобы исправить это) и * 2) * вы не проанализировали документ с включенным пространством имен (вызовите 'factory.setNamespaceAware (true)', чтобы исправить это). --- Кроме того, как вы ожидаете от нас помощи, когда мы не знаем, как выглядит XML? – Andreas

+0

Andreas - Я добавил XML-пример в исходный msg. Также я попробовал ваше предложение о builder.parse (новый InputSource (новый StringReader (compositeBodyLine))), но тогда я получаю исключение NullPointerException. – user555303

ответ

1

Стив, причиной этого может быть пространств имен, которые у вас есть на XML. Одним из способов преодоления этого является регистрация пространств имен. Более простой подход может заключаться в использовании локальных имен. Более короткая версия вашей программы приведена ниже, и она возвращает мне набор узлов, как ожидалось. Я создал минимальную тестовую программу здесь, пожалуйста, дайте мне знать, если это работает для других 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 - Я думаю, что это близко к работе за то, что мне нужно, но, FYI, я добавил метод printXpathResult() из кода, который я разместил, слегка модифицированный для вывода значения и имени узла, и он показывает имена узлов все в порядке, но значения узла (nodes.item (i) .getNodeValue()) возвращаются как null. – user555303

+0

Ramachandran G A - Хорошо, я смог получить значения. Раньше я использовал «nodes.item (i) .getTextContent()» вместо «nodes.item (i) .getNoteValue()». Благодаря!! – user555303

Смежные вопросы