使用 XPath 更改文本内容
Change text content with XPath
尽管我可以使用以下代码在节点内设置文本值
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();
}
}
您正在使用非命名空间感知方法 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
是 not 命名空间感知的,您必须在工厂上调用 setNamespaceAware(true)
,然后再向其请求 newDocumentBuilder
.
XPath 需要命名空间感知解析,如果你想通过 XPath 访问命名空间中的元素,那么你必须向 XPath
对象提供一个 NamespaceContext
来告诉它什么前缀绑定使用 - 它不继承原始 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);
尽管我可以使用以下代码在节点内设置文本值
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();
}
}
您正在使用非命名空间感知方法 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
是 not 命名空间感知的,您必须在工厂上调用 setNamespaceAware(true)
,然后再向其请求 newDocumentBuilder
.
XPath 需要命名空间感知解析,如果你想通过 XPath 访问命名空间中的元素,那么你必须向 XPath
对象提供一个 NamespaceContext
来告诉它什么前缀绑定使用 - 它不继承原始 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);