Подтвердить что ты не робот

XPath: Есть ли способ установить пространство имен по умолчанию для запросов?

Есть ли способ установить, что Java XPath имеет префикс пространства имен по умолчанию для экспрессов? Например, вместо:/html: html/html: head/html: title/text() ", запрос может быть:/html/head/title/text()

При использовании префикса пространства имен работает более элегантный способ.

Пример фрагмента кода того, что я делаю сейчас:

Node node = ... // DOM of a HTML document
XPath xpath = XPathFactory.newInstance().newXPath();

// set to a NamespaceContext that simply returns the prefix "html"
// and namespace URI ""http://www.w3.org/1999/xhtml"
xpath.setNamespaceContext(new HTMLNameSpace());

String expression = "/html:html/html:head/html:title/text()";
String value = xpath.evaluate(query, expression);
4b9b3361

Ответ 1

К сожалению, нет. Несколько лет назад были некоторые разговоры об определении пространства имен по умолчанию для JxPath, но быстрый просмотр последних документов не означает, что что-то случилось. Возможно, вы захотите потратить еще некоторое время на просмотр документов.

Одна вещь, которую вы могли бы сделать, если вы действительно не заботитесь о пространствах имен, заключается в анализе документа без них. Просто опустите вызов, который вы сейчас делаете в DocumentBuilderFactory.setNamespaceAware().

Также обратите внимание, что ваш префикс может быть любым, что вы хотите; он не должен соответствовать префиксу в документе экземпляра. Таким образом, вы можете использовать h, а не html, и минимизировать визуальный беспорядок префикса.

Ответ 2

Я действительно не пробовал это, но, согласно документации NamespaceContext, контекст пространства имен с префиксом "" (строка emtpy) считается пространством имен по умолчанию.


Я был слишком быстр на этом. Оценщик XPath не вызывает NamespaceContext для разрешения префикса ", если префикс вообще не используется в выражении XPath" /html/head/title/text () ". Теперь я перехожу к XML-деталям, о которых я не уверен на 100%, но используя выражение типа" /: html/: head/: title/text() "работает с Sun JDK 1.6.0_16 и запрашивается NamespaceContext для разрешения пустого префикса (" "). Это действительно правильное и ожидаемое поведение или ошибка в Xalan?

Ответ 3

Я знаю, что этот вопрос старый, но я просто потратил 3 часа на поиск попытки решить эту проблему, и ответ @kdgregorys помог мне многое. Я просто хотел точно указать, что я сделал, используя kdgregorys в качестве руководства.

Проблема в том, что 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);