簡體   English   中英

Java 8 Stream API:獲取特定節點之后的所有節點

[英]Java 8 Stream API: get all nodes after specific Node

我有5個節點的org.w3c.dom.NodeList UUID.randomUUID();生成的節點ID UUID.randomUUID();

Dom結構:

<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>

我需要獲取屬性為id =“ value5”的節點之后的所有節點。 因此結果應包含id = value6和id = value7的節點。

我創建了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);

因此,我可以通過Java 8 Stream API做到這一點嗎?

不幸的是,DOM API無法與其他API很好地配合使用。 此較早的答案中,我提供了一個有用的輕量級List包裝器。

這樣,您可以簡單地執行以下操作:

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);

要么

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);

您的問題令人困惑。 但是,如果您只需要在具有特定屬性的Element之后獲得節點並且它們是有序的,則可以嘗試按其屬性過濾Elements:

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;

}

我們決定將XPath用於此任務。 看起來好多了:

    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);
        }
    }

我希望這會對某人有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM