我正在使用XPath来提取URL128 XML元素的值。即使我在下面的示例中只有一个,也可以有很多这些。当我在SearchResponse元素上包含xmlns ='http://c1.net.corbis.com/'时,我得到一个空的NodeList,但当我删除该命名空间元素时,它工作正常。是否有我缺少的配置?
String xmlData = "<SearchResponse xmlns='http://c1.net.corbis.com/'><searchResultDataXML><SearchResultData><SearchRequestUID Scope='Public' Type='Guid' Value='{cded773c-c4b7-4dd8-aaee-8e5b8b7a2475}'/><StartPosition Scope='Public' Type='Long' Value='1'/><EndPosition Scope='Public' Type='Long' Value='50'/><TotalHits Scope='Public' Type='Long' Value='323636'/></SearchResultData></searchResultDataXML><imagesXML><Images><Image><ImageUID Scope='Public' Type='Guid' Value='{a6f6d3e2-2c3f-4502-9741-eae2e1bb573a}'/><CorbisID Scope='Public' Type='String' Value='42-25763849'/><Title Scope='Public' Type='String' Value='Animals figurines'/><CreditLine Scope='Public' Type='String' Value='© Ocean/Corbis'/><IsRoyaltyFree Scope='Public' Type='Boolean' Value='True'/><AspectRatio Scope='Public' Type='String' Value='0.666667'/><URL128 Scope='Public' Type='String' Value='http://cachens.corbis.com/CorbisImage/thumb/25/76/38/25763849/42-25763849.jpg'/></Image></Images></imagesXML></SearchResponse>";
InputSource source = new InputSource(new StringReader(xmlData));
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList list = null;
try {
list = (NodeList) xPath.evaluate("//URL128/@Value", source, XPathConstants.NODESET);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
for (int i = 0; i < list.getLength(); i++) {
System.out.println(list.item(i).getTextContent());
}
答案 0 :(得分:2)
嗯,长话短说,您需要为XPath
提供NamespaceContext
:
final XPath xPath = XPathFactory.newInstance().newXPath();
xPath.setNamespaceContext(new NamespaceContext() {
@Override
public Iterator<String> getPrefixes(final String namespaceURI) {
return null;
}
@Override
public String getPrefix(final String namespaceURI) {
return null;
}
@Override
public String getNamespaceURI(final String prefix) {
return "http://c1.net.corbis.com/";
}
});
final NodeList list = (NodeList) xPath.evaluate("//c:URL128/@Value", source, XPathConstants.NODESET);
for (int i = 0; i < list.getLength(); i++) {
System.out.println(list.item(i).getTextContent());
}
似乎XPath要求我们在这种情况下实现的唯一方法是getNamespaceURI(String prefix)
。
请注意,“c:URL128”中的实际前缀在这种情况下并不重要 - 您可以轻松使用“:URL128”。当做在XML中有多个名称空间时,区分它们变得很重要(如果元素相对较少,则使用Map
或一系列if-then-else
。
如果您不能或不想对前缀进行硬编码,您可以自己从XML文档中提取它们,但这需要更多的代码......
有关详细信息,另请参阅this blog post。
答案 1 :(得分:1)
对此有一个稍微简单的解决方案,它不涉及在代码中放置硬编码的URI引用...只需解析文档,并将namespace aware属性设置为false ...
String xmlData = "<SearchResponse xmlns='http://c1.net.corbis.com/'><searchResultDataXML><SearchResultData><SearchRequestUID Scope='Public' Type='Guid' Value='{cded773c-c4b7-4dd8-aaee-8e5b8b7a2475}'/><StartPosition Scope='Public' Type='Long' Value='1'/><EndPosition Scope='Public' Type='Long' Value='50'/><TotalHits Scope='Public' Type='Long' Value='323636'/></SearchResultData></searchResultDataXML><imagesXML><Images><Image><ImageUID Scope='Public' Type='Guid' Value='{a6f6d3e2-2c3f-4502-9741-eae2e1bb573a}'/><CorbisID Scope='Public' Type='String' Value='42-25763849'/><Title Scope='Public' Type='String' Value='Animals figurines'/><CreditLine Scope='Public' Type='String' Value='© Ocean/Corbis'/><IsRoyaltyFree Scope='Public' Type='Boolean' Value='True'/><AspectRatio Scope='Public' Type='String' Value='0.666667'/><URL128 Scope='Public' Type='String' Value='http://cachens.corbis.com/CorbisImage/thumb/25/76/38/25763849/42-25763849.jpg'/></Image></Images></imagesXML></SearchResponse>";
InputSource source = new InputSource(new StringReader(xmlData));
// create doc instance instead of passing source straight to XPath...
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false); // must be false
DocumentBuilder builder = factory.newDocumentBuilder();
final Document doc = builder.parse(source);
XPath xPath = XPathFactory.newInstance().newXPath();
// use doc instead
NodeList list = (NodeList) xPath.evaluate("//URL128/@Value", doc,
XPathConstants.NODESET);
for (int i = 0; i < list.getLength(); i++) {
System.out.println(list.item(i).getTextContent());
}
答案 2 :(得分:0)
如果使用spring,则可以依赖org.springframework.util.xml.SimpleNamespaceContext接口。
InputSource source = new InputSource(new StringReader(unescaped));
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList list = null;
try
{
SimpleNamespaceContext nsCtx = new SimpleNamespaceContext();
nsCtx.bindNamespaceUri("ns", "http://c1.net.corbis.com/");
xPath.setNamespaceContext(nsCtx);
list = (NodeList) xPath.evaluate("//ns:URL128/@Value", source, XPathConstants.NODESET);
} catch (Exception ex)
{
System.out.println(ex.getMessage());
}
for (int i = 0; i < list.getLength(); i++)
{
System.out.println(list.item(i).getTextContent());
}