Я знаю, что этот вопрос старый, но я потратил 3 часа на поиски решения этой проблемы, и @ kdgregorys answer очень помог мне. Я просто хотел поставить именно то, что сделал, используя kdgregorys answer в качестве руководства.
Проблема в том, что XPath в java даже не ищет пространство имен, если у вас нет префикса в запросе, поэтому для сопоставления запроса с конкретным пространством имен вы должны добавить префикс к запросу. Я использовал произвольный префикс для сопоставления с именем схемы. В этом примере я буду использовать пространство имен и запрос OP, а также префикс abc
. Ваше новое выражение будет выглядеть так:
String expression = "/abc:html/abc:head/abc:title/text()";
Затем выполните следующее
1) Убедитесь, что для вашего документа задано пространство имен.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
2) Реализация NamespaceContext
, которая разрешит ваш префикс. Этот я взял из другого поста на SO и немного изменил
.
public class NamespaceResolver implements NamespaceContext {
private final Document document;
public NamespaceResolver(Document document) {
this.document = document;
}
public String getNamespaceURI(String prefix) {
if(prefix.equals("abc")) {
// here is where you set your namespace
return "http://www.w3.org/1999/xhtml";
} else if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
return document.lookupNamespaceURI(null);
} else {
return document.lookupNamespaceURI(prefix);
}
}
public String getPrefix(String namespaceURI) {
return document.lookupPrefix(namespaceURI);
}
@SuppressWarnings("rawtypes")
public Iterator getPrefixes(String namespaceURI) {
// not implemented
return null;
}
}
3) При создании объекта XPath установите свой NamespaceContext.
xPath.setNamespaceContext(new NamespaceResolver(document));
Теперь, независимо от фактического префикса схемы, вы можете использовать свой собственный префикс, который будет сопоставлен с правильной схемой. Таким образом, ваш полный код с использованием приведенного выше класса будет выглядеть примерно так:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
Document document = factory.newDocumentBuilder().parse(sourceDocFile);
XPathFactory xPFactory = XPathFactory.newInstance();
XPath xPath = xPFactory.newXPath();
xPath.setNamespaceContext(new NamespaceResolver(document));
String expression = "/abc:html/abc:head/abc:title/text()";
String value = xpath.evaluate(query, expression);