使用 Java 更新 XML 文档
Update XML document using Java
在 Internet 上,我找到了很多关于如何实现此功能的示例,但其中 none 似乎适用于我的情况。我有一个包含 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:outcome 它将是 '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);
代码应该与上面类似,但是我没有得到结果,
你能指出我遗漏了什么吗?
亲切的问候
最大值
在计算带有名称空间的 XPATH 表达式之前,您必须做另外两件事。
DocumentBuilderFactory
实例默认不识别命名空间。所以你必须调用 setNamespaceAware(true)
.
- 创建您自己的接口实现
NamespaceContext
并将其传递给您的 XPath
实例。
这里有一个简单的 NamespaceContext
实现作为静态内部 class。这里只实现了getNamespaceURI()
方法。 (有关更多详细信息和替代实现,请参阅这篇 IBM developerWorks 文章: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();
}
}
这里是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
实现中同时声明两者。
在 Internet 上,我找到了很多关于如何实现此功能的示例,但其中 none 似乎适用于我的情况。我有一个包含 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:outcome 它将是 '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);
代码应该与上面类似,但是我没有得到结果,
你能指出我遗漏了什么吗?
亲切的问候 最大值
在计算带有名称空间的 XPATH 表达式之前,您必须做另外两件事。
DocumentBuilderFactory
实例默认不识别命名空间。所以你必须调用setNamespaceAware(true)
.- 创建您自己的接口实现
NamespaceContext
并将其传递给您的XPath
实例。
这里有一个简单的 NamespaceContext
实现作为静态内部 class。这里只实现了getNamespaceURI()
方法。 (有关更多详细信息和替代实现,请参阅这篇 IBM developerWorks 文章: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();
}
}
这里是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
实现中同时声明两者。