使用Java更新XML文档(Update XML document using Java)

编程入门 行业动态 更新时间:2024-10-11 21:24:08
使用Java更新XML文档(Update XML document using Java)

在互联网上,我找到了很多如何实现这个功能的例子,但是在我的情况下它们似乎都没有。 我有一个包含XML数据的字符串,我知道结果的XPath应该是什么样子。 比方说,我有一个xml结构,如下所示:

<?xml version="1.0"?> <m:parent xmlns:m="http://www.somescheme"> <doc:header xmlns:doc="http://www.somescheme"> <doc:documentId>137</doc:documentId> <doc:documentDescription>Some Description</doc:documentDescription> <doc:task> <doc:id>49</doc:id> <doc:name>Some Name</doc:name> <doc:description>Some Task Description</doc:description> <doc:outcome/> <doc:dueDate/> <doc:priority>50</doc:priority> </doc:task> </doc:header> <m:otherinfo>234324</m:otherInfo> </m:parent>

比方说,我需要访问和更新otherInfo,XPath将是'm:parent / m:otherInfo',我应该能够读取和设置。 对于doc:results,它将是'm:parent / doc:header / doc:task / doc:outcome'这是我需要在运行时设置的值。

Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( new InputSource("data.xml")); XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes = (NodeList) xpath.evaluate("//m:parent/doc:header/doc:task/doc:outcome", doc, XPathConstants.NODESET);

代码应该像上面那样,但是我没有得到结果,

你能指出我错过的东西吗?

亲切的问候Max

On the internet I am finding a lot of examples of how to achieve this functionality, however none of them seem to work in my case. I have an string containing XML data, and I know what the XPath of the result should look like. Say for example I have an xml structure looking like this:

<?xml version="1.0"?> <m:parent xmlns:m="http://www.somescheme"> <doc:header xmlns:doc="http://www.somescheme"> <doc:documentId>137</doc:documentId> <doc:documentDescription>Some Description</doc:documentDescription> <doc:task> <doc:id>49</doc:id> <doc:name>Some Name</doc:name> <doc:description>Some Task Description</doc:description> <doc:outcome/> <doc:dueDate/> <doc:priority>50</doc:priority> </doc:task> </doc:header> <m:otherinfo>234324</m:otherInfo> </m:parent>

Say for example I need to access and update otherInfo the XPath would be 'm:parent/m:otherInfo' which I should be able to read and set. For doc:outcome it would be 'm:parent/doc:header/doc:task/doc:outcome' This is a value I need to set at runtime.

Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( new InputSource("data.xml")); XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes = (NodeList) xpath.evaluate("//m:parent/doc:header/doc:task/doc:outcome", doc, XPathConstants.NODESET);

The code should be something like above, however I am not getting results,

Can you point out what I am missing ?

Kind Regards Max

最满意答案

在使用命名空间评估XPATH表达式之前,您还需要做两件事。

默认情况下, DocumentBuilderFactory实例不支持名称空间。 所以你必须调用setNamespaceAware(true) 。 创建自己的NamespaceContext接口实现并将其传递给XPath实例。

这里有一个简单的NamespaceContext实现作为静态内部类。 这里只实现了getNamespaceURI()方法。 ( 有关更多详细信息和替代实现,请参阅此IBM developerWorks文章: 在XPath中使用Java语言NamespaceContext对象 )

static class MyNamespaceContext implements NamespaceContext { @Override public String getNamespaceURI(String prefix) { if(prefix == null) { throw new IllegalArgumentException(); } else if(prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) { return XMLConstants.NULL_NS_URI; } else if(prefix.equals(XMLConstants.XML_NS_PREFIX)) { return XMLConstants.XML_NS_URI; } else if(prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; } else if(prefix.equals("m")) { return "http://www.somescheme"; } else if(prefix.equals("doc")) { return "http://www.somescheme"; } else { return XMLConstants.NULL_NS_URI; } } @Override public String getPrefix(String namespaceURI) { throw new UnsupportedOperationException(); } @Override public Iterator getPrefixes(String namespaceURI) { throw new UnsupportedOperationException(); } }

这里是DocumentBuilderFactory的部分:

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); Document doc = documentBuilderFactory.newDocumentBuilder().parse( new InputSource("data.xml")); XPath xpath = XPathFactory.newInstance().newXPath(); xpath.setNamespaceContext(new MyNamespaceContext()); NodeList nodes = (NodeList) xpath.evaluate( "//m:parent/doc:header/doc:task/doc:outcome", doc, XPathConstants.NODESET);

两个名称空间前缀实际上链接到相同的名称空间URI。 实际上,您只能在XPATH表达式中使用一个前缀,例如"//doc:parent/doc:header/doc:task/doc:outcome"并且您不需要在NamespaceContext实现中声明这两个前缀。

You have to do two additional things before you can evaluate XPATH expressions with namespaces.

The DocumentBuilderFactory instance is not namespace aware by default. So you have to call setNamespaceAware(true). Create your own implementation of the interface NamespaceContext and pass it to your XPath instance.

Here a simple NamespaceContext implementation as a static inner class. Only the getNamespaceURI() method is implemented here. (See this IBM developerWorks article for more details and alternative implementations: Using the Java language NamespaceContext object with XPath)

static class MyNamespaceContext implements NamespaceContext { @Override public String getNamespaceURI(String prefix) { if(prefix == null) { throw new IllegalArgumentException(); } else if(prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) { return XMLConstants.NULL_NS_URI; } else if(prefix.equals(XMLConstants.XML_NS_PREFIX)) { return XMLConstants.XML_NS_URI; } else if(prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) { return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; } else if(prefix.equals("m")) { return "http://www.somescheme"; } else if(prefix.equals("doc")) { return "http://www.somescheme"; } else { return XMLConstants.NULL_NS_URI; } } @Override public String getPrefix(String namespaceURI) { throw new UnsupportedOperationException(); } @Override public Iterator getPrefixes(String namespaceURI) { throw new UnsupportedOperationException(); } }

Here the part with the DocumentBuilderFactory:

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); Document doc = documentBuilderFactory.newDocumentBuilder().parse( new InputSource("data.xml")); XPath xpath = XPathFactory.newInstance().newXPath(); xpath.setNamespaceContext(new MyNamespaceContext()); NodeList nodes = (NodeList) xpath.evaluate( "//m:parent/doc:header/doc:task/doc:outcome", doc, XPathConstants.NODESET);

The two namespace prefixes are actually linked to the same namespace URI. In fact you can use only one prefix in your XPATH expression like "//doc:parent/doc:header/doc:task/doc:outcome" and you don't need to declare both in your NamespaceContext implementation.

更多推荐

本文发布于:2023-08-02 20:01:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1379763.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:文档   XML   Java   Update   document

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!