使用XPath更改文本内容

时间:2015-02-17 18:52:47

标签: java xml xpath element xmlnode

虽然我可以使用下面的代码

在节点内设置文本值
private static void setPhoneNumber(Document xmlDoc, String phoneNumber) {
    Element root = xmlDoc.getDocumentElement();     
    Element phoneParent = (Element) root.getElementsByTagName("gl-bus:entityPhoneNumber").item(0);      
    Element phoneElement = (Element) phoneParent.getElementsByTagName("gl-bus:phoneNumber").item(0);    
    phoneElement.setTextContent(phoneNumber);       
}

我不能对XPath做同样的事情,因为我为节点对象

得到了null
private static void setPhoneNumber(Document xmlDoc, String phoneNumber) {
    try {
        NodeList nodes = (NodeList) xPath.evaluate("/gl-cor:entityInformation/gl-bus:entityPhoneNumber/gl-bus:phoneNumber", xmlDoc, XPathConstants.NODESET);
        Node node = nodes.item(0);
        node.setTextContent(phoneNumber);
    } catch (XPathExpressionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
 }

1 个答案:

答案 0 :(得分:1)

您正在使用非命名空间感知方法getElementsByTagName(),并向其传递包含冒号的元素名称这一事实表明您在解析XML时未正确处理命名空间。如果您的XML是以名称空间感知的方式解析的,那么这不应该有效,但是类似

String namespace = // the namespace URI bound to the gl-bus prefix in your doc
Element phoneParent = (Element) root.getElementsByTagNameNS(namespace, "entityPhoneNumber").item(0);

会正常工作。请注意,标准Java DocumentBuilderFactory默认情况下名称空间,在您要求setNamespaceAware(true)之前,必须在工厂中调用newDocumentBuilder

XPath需要名称空间感知解析,如果要通过XPath访问名称空间中的元素,则必须向NamespaceContext对象提供XPath以告诉它使用哪些前缀绑定 - 它不继承原始XML的前缀绑定。令人讨厌的是,核心Java库中没有提供NamespaceContext的默认实现,因此您必须自己编写或使用第三方实现,例如Spring's SimpleNamespaceContext。有了这个:

SimpleNamespaceContext ctx = new SimpleNamespaceContext();
ctx.bindNamespaceUri("g", namespace); // the same URI as before
ctx.bindNamespaceUri("c", ...); // the namespace bound to gl-cor:
xPath.setNamespaceContext(ctx);

NodeList nodes = (NodeList) xPath.evaluate("/c:entityInformation/g:entityPhoneNumber/g:phoneNumber", xmlDoc, XPathConstants.NODESET);