Выберите узел, используя xpath и jdom
У меня есть документ в формате xform
<?xml version="1.0" encoding="UTF-8"?><h:html xmlns:h="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jr="http://openrosa.org/javarosa">
<h:head>
<h:title>Summary</h:title>
<model>
<instance>
<data vaultType="nsp_inspection.4.1">
<metadata vaultType="metadata.1.1">
<form_start_time type="dateTime" />
<form_end_time type="dateTime" />
<device_id type="string" />
<username type="string" />
</metadata>
<date type="date" />
<monitor type="string" />
</data>
</instance>
</model>
</h:head>
Я хотел бы выбрать элемент данных из xform, используя xpath и jdom
XPath xpath = XPath.newInstance("h:html/h:head/h:title/");
кажется, работает нормально и выбирает элемент заголовка, но
XPath xpath = XPath.newInstance("h:html/h:head/model");
не выбирает модельный элемент. Я думаю, это как-то связано с пространством имен.
1 ответ
Несколько вещей. Вы действительно должны использовать JDOM 2.0.x ... (2.0.5 - последняя версия). XPath API в версиях 2.0.x намного лучше, чем в JDOM 1.x: см. https://github.com/hunterhacker/jdom/wiki/JDOM2-Feature-XPath-Upgrade
@wds прав в том, что не имеет правильного пространства имен для элементов xforms тоже... и именно поэтому ваш XPath работает, потому что он имеет то же пространство имен, что и элементы xhtml с префиксом 'h'. Ваш код, скорее всего, будет сломан.
Пространства имен в XPath часто путают людей, потому что каждое пространство имен в XPath должно иметь префикс. Даже если что-то является пространством имен по умолчанию в XML (без префикса, как ваш элемент 'model'), оно должно быть в XPath. запросы без префикса в XPath всегда ссылаются на пространство имен "no namespace".... (спецификация XPath: http://www.w3.org/TR/xpath/)
QName в тесте узла раскрывается в расширенное имя с использованием объявлений пространства имен из контекста выражения. Это происходит так же, как расширение для имен типов элементов в начальном и конечном тегах, за исключением того, что пространство имен по умолчанию, объявленное с помощью xmlns, не используется: если QName не имеет префикса, то URI пространства имен равен нулю (это то же самое способ расширения имен атрибутов). Ошибка, если у QName есть префикс, для которого нет никакого объявления пространства имен в контексте выражения
Предполагая, что @wds является верным, а пространство имен для элемента модели должно быть " http://www.w3.org/2002/xforms ", тогда ваше деление пространства имен в вашем документе должно быть xmlns="http://www.w3.org/2002/xforms". Но это пространство имен является пространством имен "по умолчанию", а URI для пространства имен без префикса в вашем запросе XPath - "".
Чтобы получить доступ к пространству имен http://www.w3.org/2002/xforms в вашем XPath, вы должны дать ему префикс для контекста XPath, скажем, xpns (для пространства имен xpath). В JDOM 1.x вы добавляете это пространство имен с помощью:
XPath xpath = XPath.newInstance("/h:html/h:head/xpns:model");
xpath.addNamespace(Namespace.getNamespace("xpns", "http://www.w3.org/2002/xforms");
Element model = (Element)xpath.selectSingleNode(mydoc)
Обратите внимание, как это добавляет xpns к запросу. Также обратите внимание, что я "привязал" ссылку h: / html к корню "/" документа, что повысит производительность оценки запроса.
В JDOM 2.x API-интерфейс XPath значительно лучше (хотя в некоторых случаях это может показаться излишним).
XPathFactory xpf = XPathFactory.instance();
XPathExpression<Element> xpath = xpf.compile("/h:html/h:head/xpns:model",
Filters.element(), null,
Namespace.getNamesace("xpns", "http://www.w3.org/2002/xforms"));
Element model = xpath.evaluateFirst(mydoc);
Узнайте больше о новом API XPath в javadoc JDOM 2.x: javadoc XPathFactory.compile(...)