【问题标题】:Update empty XML element using XPATH and DOM in Java在 Java 中使用 XPATH 和 DOM 更新空 XML 元素
【发布时间】:2021-06-16 19:43:14
【问题描述】:

我将以下 XML 文档存储为字符串,并希望使用 XPATH 和 DOM 更新为空的 SubID 元素。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.com/2.0/" xmlns:pfx="http://example.com/1.0">
<soapenv:Header/>
<soapenv:Body>
    <soapenv:Fault>
        <faultcode>soapenv:Client</faultcode>
        <faultstring>Authentication Failed</faultstring>
        <detail>
        <pfx:Fault>
            <ns2:MessageHeader xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:ns1="example.com/1.0/" xmlns:ns2="http://www.example.com/MessageHeader/1.0/">
                <ns2:SubId></ns2:SubId>
                <ns2:CnsmrId></ns2:CnsmrId>
            </ns2:MessageHeader>
        </pfx:Fault>
        </detail>
    </soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>

我使用以下代码首先使用 xpath 获取节点并使用 DOM 更新它。由于 XML 文档使用命名空间,我在 xpath 中使用了local-name()

public void updateXML(String xmlString, String textToAdd) {
    Document responseDoc = convertStringToXMLDocument(xmlString.trim());
    responseDoc.getDocumentElement().normalize();

    XPath xpath = XPathFactory.newInstance().newXPath();
    String destinationPath = "//*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Fault']/*[local-name()='detail']/*[local-name()='Fault']/*[local-name()='MessageHeader']/*[local-name()='SubId']";

    Node destinationNode = (Node) xpath.compile(destinationPath).evaluate(responseDoc, XPathConstants.NODE);
    destinationNode.setNodeValue(textToAdd);
    String respDoc = convertDOMtoXMLString(responseDoc);
    System.out.println(respDoc);
}

private static Document convertStringToXMLDocument(String xmlString)   {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = null;
    factory.setNamespaceAware(true);
    builder = factory.newDocumentBuilder();
    Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
    return doc;
}

private static String convertDOMtoXMLString(Document doc) {
    DOMSource domSource = new DOMSource(doc);
    StringWriter writer = new StringWriter();
    StreamResult result = new StreamResult(writer);
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer;
    transformer = tf.newTransformer();
    transformer.transform(domSource, result);
    return writer.toString();
}

在目标节点中设置值后,我尝试将其转换回字符串并打印以进行验证,但我看到 SubId 字段已折叠并且没有添加任何内容。这是我得到的输出(仅发布 XML 输出的相关部分):

<pfx:Fault>
    <ns2:MessageHeader xmlns:ns1="qwerty.com/1.0/" xmlns:ns2="http://www.abcd.com/MessageHeader/1.0/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <ns2:SubId />
        <ns2:CnsmrId />
    </ns2:MessageHeader>
</pfx:Fault>

我做错了什么?

【问题讨论】:

    标签: java xml xpath soap


    【解决方案1】:

    我发现如果元素为空,使用 setNodeValue 将不起作用,我们可以创建一个文本节点,然后将其作为子节点附加到目标节点中。

    public void updateXML(String xmlString, String textToAdd) {
        Document responseDoc = convertStringToXMLDocument(xmlString.trim());
        responseDoc.getDocumentElement().normalize();
    
        XPath xpath = XPathFactory.newInstance().newXPath();
        String destinationPath = "//*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Fault']/*[local-name()='detail']/*[local-name()='Fault']/*[local-name()='MessageHeader']/*[local-name()='SubId']";
    
        Node destinationNode = (Node) xpath.compile(destinationPath).evaluate(responseDoc, XPathConstants.NODE);
        Text txt = responseDoc.createTextNode("Hello");
        destinationNode.appendChild(txt);
        String respDoc = convertDOMtoXMLString(responseDoc);
        System.out.println(respDoc);
    }
    

    参考:Adding a Text Node to a DOM Document

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-01
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多