2017-02-17 17 views
0

org.w3c.dom.NodeListに5ノードあります。 UUID.randomUUID();Java 8ストリーム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 = "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ストリームAPIでこれを行うにはできますか?

+2

'attribute> 5 ' –

+1

@AndriiAbramovでフィルタリングしようとすると、idは生成された値です。私はそれらを比較することはできません。 –

+1

jdk-9では、 '.dropWhile(i - > i!= 5).skip(1)' – Eugene

答えて

2

残念ながら、DOM APIは、他のAPIとうまく再生されません。便利な軽量のListラッパーをthis earlier answerに入れました。これにより

、あなたは単に行うことができます:

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

「null」でストリームを終了する能力が不足しているため、Stream.iterate(element.getOwnerDocument()。getElementById( "value5")、Node :: getNextSibling) – 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

ありがとう!しかし、残念なことにid値はランダムなuuidによって生成されます: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); 
     } 
    } 

私はそれが誰かのために役立つことを願っています。

関連する問題