Xpath Java получает элемент, проверяя значение

1

Я пытаюсь использовать Xpath для синтаксического анализа строки xml, но я не знаю, как использовать выражение для получения того, что я хочу.

У меня есть следующий xml-контент:

<root1>
    <root2>
        <A>something</A>
        <B>something</B>
        <C>
            <D>
                <E>DataE</E>
                <F>DataF</F>
                <G>something</G>
                <H>something</H>
                <I>
                    <J>
                      <K>DataK</K>
                      <L>DataL</L>
                    </J>
                </I>
            </D>
            <D>
                <E>DataE_ERROR</E>
                <F>DataF</F>
                <G>something</G>
                <H>something</H>
                <I>
                    <J>
                      <K>DataK</K>
                      <L>DataL</L>
                    </J>
                </I>
            </D>
        </C>
     </root2>
</root1>

Я хотел бы получить значение F, K, L, когда значение E является DataE, например.

Я использую для этого Xpath, но я не могу найти хорошее выражение!

вот мой код Java:

public void getit()
{
    String xml = "The xml above";

    DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
    DocumentBuilder b = f.newDocumentBuilder();
    Document d = b.parse(new InputSource(new StringReader(xml)));
    d.getDocumentElement().normalize();

    // No idea ! how can i make it work by testing the value of E
    String expression = "//E/text()|//F/text()|//K/text()|//L/text()";

    XPath xPath = XPathFactory.newInstance().newXPath();
    Object result = xPath.compile(expression).evaluate(d, XPathConstants.NODESET);

    NodeList nodes = (NodeList) result;
    for (int i = 0; i < nodes.getLength(); i++) {
        System.out.println(nodes.item(i).getNodeValue()); 
    }

}
Теги:
xpath
expression

1 ответ

3
Лучший ответ

Просто чтобы я мог гарантировать, что запрос работает, я изменил XML-пример следующим образом...

<root1>
    <root2>
        <A>something</A>
        <B>something</B>
        <C>
            <D>
                <E>DataE</E>
                <F>DataF 1</F>
                <G>something</G>
                <H>something</H>
                <I>
                    <J>
                        <K>DataK 1</K>
                        <L>DataL 1</L>
                    </J>
                </I>
            </D>
            <D>
                <E>DataE_ERROR</E>
                <F>DataF 2</F>
                <G>something</G>
                <H>something</H>
                <I>
                    <J>
                        <K>DataK 2</K>
                        <L>DataL 2</L>
                    </J>
                </I>
            </D>
        </C>
    </root2>
</root1>

Магия здесь...

String expression = "//F[ancestor::D/E[text()='DataE']]|//K[ancestor::D/E[text()='DataE']]|//L[ancestor::D/E[tex

В принципе, это читает...

Найдите любой узел F, у которого есть предок, содержащий D с дочерним элементом E, текст которого равен DataE или...

Теперь это важно, вы можете использовать ../ чтобы найти родительский узел, но K и L похоронены в под-узлах, и я не уверен, что они могут быть более глубокими или неглубокими, поэтому я пошел на этот метод.

Возможно, вам придется немного его доработать, но я считаю, что отношения D/E были важны.

С этим (и приведенным ниже примером) я смог создать следующий вывод...

Found DataF 1
Found DataK 1
Found DataL 1

Пример Runnable:

public class TestXPath {

    public static void main(String[] args) {
        String xml = "The xml above";

        try {
            DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
            DocumentBuilder b = f.newDocumentBuilder();
            Document d = b.parse(new File("Values.xml"));
            d.getDocumentElement().normalize();

            String expression = "//F[ancestor::D/E[text()='DataE']]|//K[ancestor::D/E[text()='DataE']]|//L[ancestor::D/E[text()='DataE']]";
            XPath xPath = XPathFactory.newInstance().newXPath();
            Object result = xPath.compile(expression).evaluate(d, XPathConstants.NODESET);

            NodeList nodes = (NodeList) result;
            for (int i = 0; i < nodes.getLength(); i++) {

                Node node = nodes.item(i);
                System.out.println("Found " + node.getTextContent());
            }
        } catch (ParserConfigurationException | SAXException | IOException | XPathExpressionException | DOMException exp) {
            exp.printStackTrace();
        }
    }

}
  • 0
    Это просто потрясающе, спасибо, если я хотел бы с примером добавить другое отношение между J и K (показывать J только если K = dataK), как я могу это сделать?
  • 0
    Начнем с того, что этот запрос будет работать ... Я подозреваю что-то вроде //J[ancestor::K[text()='DataK']] или что-то может сделать это ...
Показать ещё 8 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню