Как сопоставить строку, которая заканчивается числом, используя XPath - PullRequest
0 голосов
/ 10 октября 2018

Проблема в том, что я пытаюсь создать выражение XPath, чтобы получить узлы, имеющие атрибуты XXX, имеющие значения, такие как TP *, где звездочка - это число.Предположим, у меня есть этот XML-файл

<tagA attA="VAL1">text</tagA>
<tagB attB="VAL333">text</tagB>
<tagA attA="VAL2">text</tagA>
<tagA attA="V2">text</tagA>

Таким образом, выражение xpath должно получить мне все tagA с атрибутом attrA со значениями с шаблоном VAL*
//tagA[@attrA[matches('VAL\d')]]: не работает

Любая помощь, пожалуйста?

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

matches() требует XPath 2.0 , но javax.xml.xpath в Java 8 поддерживает только XPath 1.0.

Кроме того, первый аргумент matches() это строка для сопоставления.Итак, вы хотите:

//tagA[@attrA[matches(., 'VAL\d')]]

Это ищет "VAL" плюс одну цифру в любом месте значения атрибута @attrA.См. Регулярное выражение в ответе @ jschnasse , если вы хотите сопоставить всю строку с несколькими / необязательными суффиксами цифр (XPath 2.0) или ответ Андерссона для решения XPath 1.0.

0 голосов
/ 10 октября 2018

Если вам нужно решение XPath 1.0, попробуйте следующее:

//tagA[boolean(number(substring-after(@attA, "VAL"))) or number(substring-after(@attA, "VAL")) = 0]

Если @attA не может быть "VAL0", тогда просто

//tagA[boolean(number(substring-after(@attA, "VAL")))]
0 голосов
/ 10 октября 2018

Добавьте квантификатор (*, +, ...) к вашему \d.Попробуйте

'^VAL\d*$'

Как указало @ kjhughes .Это не будет работать со стандартной Java, потому что даже текущая версия Java 11 не поддерживает XPath 2.0.Однако вы можете использовать Saxon , если вам нужна поддержка XPath 2.0.

Саксонский пример (Это вариант ответа с использованием javax.xml )

Processor processor = new Processor(false);

@Test
public void xpathWithSaxon() {
    String xml = "<root><tagA attA=\"VAL1\">text</tagA>\n" + "<tagB attB=\"VAL333\">text</tagB>\n"
                    + "<tagA attA=\"VAL2\">text</tagA>\n" + "<tagA attA=\"V2\">text</tagA>\n" + "</root>";
    try (InputStream in = new ByteArrayInputStream(xml.getBytes("utf-8"));) {
        processFilteredXmlWith(in, "//root/tagA[matches(@attA,'^VAL\\d*$')]", (node) -> {
            printItem(node, System.out);
        });
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

private void printItem(XdmItem node, PrintStream out) {
    out.println(node);
}

public void processFilteredXmlWith(InputStream in, String xpath, Consumer<XdmItem> process) {
    XdmNode doc = readXmlWith(in);
    XdmValue list = filterNodesByXPathWith(doc, xpath);
    list.forEach((node) -> {
        process.accept(node);
    });

}

private XdmNode readXmlWith(InputStream xmlin) {
    try {
        return processor.newDocumentBuilder().build(new StreamSource(xmlin));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

private XdmValue filterNodesByXPathWith(XdmNode doc, String xpathExpr) {
    try {
        return processor.newXPathCompiler().evaluate(xpathExpr, doc);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Prints

<tagA attA="VAL1">text</tagA>

<tagA attA="VAL2">text</tagA>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...