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