java - 使用 xpath 编辑 xml 上的值会导致 java 中的 nullpointerexception
问题描述
我们正在尝试使用 Java 在以下 xml 文件中编辑 number、dateFrom 和 dateTo:
<?xml version="1.0" encoding="UTF-8"?>
<urn:receive
xmlns:urn="urn:xxx"
xmlns:ns="xxx"
xmlns:ns1="xxx"
xmlns:urn1="urn:xxx">
<ns:info>
<ns:TransaktionIdentifikator>xxx-xxx-xxx-xxx-xxx</ns:TransaktionIdentifikator>
<ns:TransaktionTid>2015-11-22T12:00:00.146+02:00</ns:TransaktionTid>
</ns:info>
<urn:give>
<urn:giveNumber>
<ns1:number>12345678</ns1:number>
</urn:giveNumber>
<urn:giveDates>
<urn1:dateFrom>2021-07-01</urn1:dateFrom>
<urn1:dateTo>2021-09-30</urn1:dateTo>
</urn:giveDates>
</urn:give>
</urn:receive>
我们使用 xpath 解析 xml 文件,然后使用以下代码行使用转换器更新 xml 文件:
public class test {
public void receiveFunc() {
String serviceResponse = "";
String tests = "12344321";
try {
// our XML file for this example
File xmlFile = new File("{name}.xml");
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
DocumentBuilder b = f.newDocumentBuilder();
Document doc = b.parse(xmlFile);
doc.getDocumentElement().normalize();
XPath xPath = XPathFactory.newInstance().newXPath();
Node SENummer = (Node) xPath
.compile("/urn:receive/urn:give/urn:giveNumber/ns1:number")
.evaluate(doc, XPathConstants.NODE);
SENummer.setTextContent(tests);
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.setOutputProperty(OutputKeys.METHOD, "xml");
tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
DOMSource domSource = new DOMSource(doc);
StreamResult sr = new StreamResult(new File("{name}.xml"));
tf.transform(domSource, sr);
} catch (Exception e) {
e.printStackTrace();
}
}
}
请注意,在上面的示例中,应该使用值为“12344321”的字符串 test 更新该数字,但这不会发生,并且我们会收到一个空指针异常。我们认为异常是因为这条线引起的:
Node SENummer = (Node) xPath
.compile("/urn:receive/urn:give/urn:giveNumber/ns1:number")
.evaluate(doc, XPathConstants.NODE);
也许它没有正确解决。在我们找出导致空指针异常的原因之后,dateTo 和 dateFrom 应该很容易更新。
堆栈跟踪:
java.lang.NullPointerException
at dk.skat.rsu.b2b.sample.test.receiveFunc(test.java:173)
at dk.skat.rsu.b2b.sample.mvc.ServiceTestAction.execute(ServiceTestAction.java:62)
at org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:58)
at org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:67)
at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:305)
at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:852)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:206)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:219)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:530)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626)
at java.lang.Thread.run(Thread.java:748)## Heading ##
解决方案
给定您的 XML,最短的代码是利用 DOM 文档的查找方法来动态启动命名空间上下文:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse("sample1.xml");
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
return document.lookupNamespaceURI(prefix);
}
@Override
public String getPrefix(String namespaceURI) {
return document.lookupPrefix(namespaceURI);
}
@Override
public Iterator getPrefixes(String namespaceURI) {
return null;
}
});
Node SENummer = (Node)xpath.evaluate("/urn:receive/urn:give/urn:giveNumber/ns1:number", document, XPathConstants.NODE);
推荐阅读
- java - 邮件格式类型 JAVA
- android - 有没有办法在不使用子项的情况下使 Firebase 搜索查询不区分大小写?
- r - 闪亮的多个类别的PLoty
- cmake - 大型项目中与 cmake 的内部依赖关系
- ffmpeg - 我无法在我的应用程序中获取剪切的音乐文件
- firebase - 使用 getDownloadURL 的 Firebase 存储是每次需要时检索带有 url 的文件还是将其下载到客户端一次更好?
- pine-script - Pinescript - 编码触发器/触发器数组
- java - 当资金已发送到本地 regtest 网络上的特定比特币地址时,我如何获得通知?
- django - Django - inlineformset 创建视图 NOT NULL 约束失败
- python-3.x - 正则表达式匹配两个子字符串之间的段落