Java 8 Stream API: erhalten Sie alle Knoten nach einem bestimmten Knoten

Habe ich org.w3c.dom.NodeList mit 5 Knoten. Knoten-ids generiert UUID.randomUUID();

Dom-Struktur:

<section id="3" prefix="s1">
  <paragraph id="value3">
  ...
  </paragraph>
  <paragraph id="value4">
  ...
  </paragraph>
  <paragraph id="value5">
  ...
  </paragraph>
  <paragraph id="value6">
  ...
  </paragraph>
  <paragraph id="value7">
  ...
  </paragraph>
</section>

Ich brauchen, um alle Knoten nach Knoten mit Attribut id=“value5″. Also das Ergebnis sollte enthalten Knoten mit der id=value6 und id=value7.

Ich erstellt Stream<Element>:

NodeList children = element.getChildNodes();
Stream<Element> elementStream = IntStream.range(0, children.getLength())
                                         .mapToObj(children::item)
                                         .filter(Element.class::isInstance)
                                         .map(Element.class::cast);

So, Könnte ich das irgendwie mit Java 8 Stream API?

  • Versuchen Sie, die filter durch attribute > 5
  • id generiert Wert. Ich kann nicht zu vergleichen.
  • Im jdk-9 konnten Sie so etwas tun: .dropWhile(i -> i != 5).skip(1)
  • Danke. Leider verwenden wir die jdk-8.



3 Replies
  1. 3

    Leider die DOM-API nicht gut spielen mit anderen APIs. Ich habe ein nützliches leichte List wrapper in diese frühere Antwort.

    Mit dieser, könnten Sie einfach tun:

    List<Node> list = XmlUtil.asList(element.getChildNodes());
    list = list.subList(
        list.indexOf(element.getOwnerDocument().getElementById("value5"))+1, list.size());
    
    Stream<Element> stream = list.stream()
        .filter(Element.class::isInstance).map(Element.class::cast);

    oder

    List<Node> list = XmlUtil.asList(element.getChildNodes());
    Stream<Element> stream = IntStream.range(
            list.indexOf(element.getOwnerDocument().getElementById("value5"))+1, list.size())
        .mapToObj(list::get).filter(Element.class::isInstance).map(Element.class::cast);
    • Eine alternative Richtung wäre Stream.iterate(element.getOwnerDocument().getElementById( "value5"), Node::getNextSibling), was leider leidet unter dem fehlen einer Fähigkeit, um das Ende stream bei null würde, was bringen uns zurück zu Java 9, wo diese Probleme behoben sind.
    • Vielen Dank für Ihre Antwort, aber wir entschieden uns für die Verwendung von XPath für diese Aufgabe.
  2. 2

    Ihre Frage ist ruhig verwirrend. Aber wenn Sie benötigen, um nur die Knoten nach Elements mit einem bestimmten Attribut, und Sie bestellt, Sie können versuchen, die filter-Elemente durch Ihre Attribute:

    public List<Element> filterElements(NodeList items, int attributeStart){
    
        List<Element> result = IntStream.range(0, items.getLength())
                .mapToObj(children::item)
                .filter(Element.class::isInstance)
                .map(Element.class::cast)
                .filter(e -> Integer.parseInt(e.getAttribute("id")) > attributeStart)
                .collect(Collectors.toList());
    
        return result;
    
    }
    • Vielen Dank! Aber leider-id-Wert generiert zufällige uuid: UUID.randomUUID(); Und ich kann nicht vergleichen.
    • Ich aktualisiert meine Frage.
    • und nun, meine Antwort scheint zu sein, blöd 🙁 gibt es eine Reihenfolge-Regel für die UUID? Könnten wir Sie zu Sortieren?
    • Sorry für die unklare Frage. Unsere ids nur zufällige Werte, und wir können nicht Sie zu Sortieren:(
  3. 1

    Entschieden wir uns für XPath für diese Aufgabe. Es sieht viel besser aus:

        private static final String EXPRESSION_TEMPLATE = "//*[@%s='%s']";
        private static final String ID_ATTR = "id";
        //some code here
        @Override
        public NodeList lookupSiblingsAfterId(Element aRootElement, String id) {
            try {
                if (null == id) {
                    throw new IllegalArgumentException("Invalid id parameter");
                }
                return (NodeList)xpath.newXPath().evaluate(String.format(EXPRESSION_TEMPLATE, ID_ATTR, id) + "[last()]/following-sibling::*", aRootElement, XPathConstants.NODESET);
            } catch (XPathExpressionException e) {
                LOGGER.error("Can't evaluate XPath expression", e);
                throw new RuntimeException(e);
            }
        }

    Ich hoffe, es wäre hilfreich für jemanden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.