2017-02-17 95 views
0

我有org.w3c.dom.NodeList 5个节点。通过UUID.randomUUID();Java 8 Stream API:获得特定节点后的所有节点

DOM结构生成的节点的ID:

<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 = “值5” 节点后能得到的所有节点。所以结果应该包含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个流API做到这一点?

+2

尝试通过'attribute> 5'来过滤它们 –

+1

@AndriiAbramov,id是生成值。我无法比较它们。 –

+1

在jdk-9中,你可以这样做:'.dropWhile(i - > i!= 5).skip(1)' – Eugene

回答

2

遗憾的是,DOM API不与其他的API发挥好。我在this earlier answer中提供了一个有用的轻量级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); 
+2

替代方案方向将是'Stream.iterate(element.getOwnerDocument()。getElementById(“value5”),Node :: getNextSibling)',不幸的是,由于缺乏'null'结束流的能力,这会带给我们回到Java 9,这些问题已经解决了。 – Holger

+0

谢谢你的回答,但是我们决定使用XPath来完成这个任务。 –

2

你的问题是安静的混乱。但是,如果你需要一个元素之后只得到节点与特定的属性,它们是有序的,你可以尝试通过自己的属性过滤元件:

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; 

} 
+0

非常感谢!但不幸的是,由随机uuid生成的id值:UUID.randomUUID();我无法比较它们。 –

+0

我已更新我的问题。 –

+0

@AndrewNepogoda现在我的答案似乎是愚蠢的:( 是否有UUID的任何订单规则?我们可以对它们进行排序吗? –

0

我们决定使用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); 
     } 
    } 

我希望这会对某人有所帮助。

相关问题