2013-06-27 39 views
0

我使用Jericho HTML Parser解析一些畸形的HTML。特別是我試圖獲取所有文本節點,處理文本,然後將其替換。轉換迭代到了以跳過索引循環對象

我想跳過從處理的具體內容。例如,我想跳過所有元素,以及任何具有屬性class =「noProcess」的元素。所以,如果一個div的class =「noProcess」,那麼我想跳過這個div和所有的孩子處理。但是,我希望這些跳過的元素在處理後返回到輸出。

傑里科爲所有節點的迭代器,但我不知道如何跳過從迭代器的全部元素。這裏是我的代碼:

private String doProcessHtml(String html) { 
     Source source = new Source(html); 
     OutputDocument outputDocument = new OutputDocument(source); 

     for (Segment segment : source) { 
      if (segment instanceof Tag) { 
       Tag tag = (Tag) segment; 
       System.out.println("FOUND TAG: " + tag.getName()); 

       // DO SOMETHING HERE TO SKIP ENTIRE ELEMENT IF IS <A> OR CLASS="noProcess" 

      } else if (segment instanceof CharacterReference) { 
       CharacterReference characterReference = (CharacterReference) segment; 
       System.out.println("FOUND CHARACTERREFERENCE: " + characterReference.getCharacterReferenceString()); 
      } else { 
       System.out.println("FOUND PLAIN TEXT: " + segment.toString()); 
       outputDocument.replace(segment, doProcessText(segment.toString())); 
      } 
     } 

     return outputDocument.toString(); 
    } 

它看起來並不像使用ignoreWhenParsing()方法的工作,我作爲解析器只是對待「忽略」元素爲文本。我想,如果我可以將Iterator循環轉換爲for(int i = 0; ...)循環,我可能可以通過修改i來指向EndTag來跳過元素及其所有子元素然後繼續循環....但不確定。

+0

使用'continue'關鍵字怎麼樣? – sanbhat

+0

我可以繼續使用,但下一個細分將成爲我想跳過的元素的下一個孩子。它的工作方式是迭代器返回所有分段。我需要的東西說:你想跳過的元素的EndTag在位置X.所以跳到位置X並繼續 – user2287359

回答

0

這應該工作。

String skipTag = null; 
for (Segment segment : source) { 
    if (skipTag != null) { // is skipping ON? 
     if (segment instanceof EndTag && // if EndTag found for the 
      skipTag.equals(((EndTag) segment).getName())) { // tag we're skipping 
      skipTag = null; // set skipping OFF 
     } 
     continue; // continue skipping (or skip the EndTag) 
    } else if (segment instanceof Tag) { // is tag? 
     Tag tag = (Tag) segment; 
     System.out.println("FOUND TAG: " + tag.getName()); 
     if (HTMLElementName.A.equals(tag.getName()) { // if <a> ? 
      skipTag = tag.getName(); // set 
      continue; // skipping ON 
     } else if (tag instanceof StartTag) { 
      if ("noProcess".equals(// if <tag class="noProcess" ..> ? 
        ((StartTag) tag).getAttributeValue("class"))) { 
       skipTag = tag.getName(); // set 
       continue; // skipping ON 
      } 
     } 
    } // ... 
} 
+0

繼續不會這樣做。它不會跳過整個元素。它只是跳過特定的Tag對象。 – user2287359

+0

@ user2287359請檢查更新。 –

0

我想你可能想考慮重新設計你的細分市場的方式。有沒有一種方法來解析html,使得每個段都是一個包含嵌套子元素列表的父元素?這樣,你可以這樣做:

for (Segment segment : source) { 
     if (segment instanceof Tag) { 
      Tag tag = (Tag) segment; 
      System.out.println("FOUND TAG: " + tag.getName()); 

      // DO SOMETHING HERE TO SKIP ENTIRE ELEMENT IF IS <A> OR CLASS="noProcess" 
      continue; 

     } else if (segment instanceof CharacterReference) { 
      CharacterReference characterReference = (CharacterReference) segment; 
      System.out.println("FOUND CHARACTERREFERENCE: " + characterReference.getCharacterReferenceString()); 
      for(Segment child : segment.childNodes()) { 
       //Use recursion to process child elements 
       //You will want to put your for loop in a separate method so it can be called recursively. 
      } 
     } else { 
      System.out.println("FOUND PLAIN TEXT: " + segment.toString()); 
      outputDocument.replace(segment, doProcessText(segment.toString())); 
     } 
    } 

沒有更多的代碼來檢查它很難確定是否重組分割元素,甚至有可能還是值得的。

0

設法有通過使用標記的元素對象的getEnd()方法的工作溶液。如果它們的最終位置小於您設置的位置,則該想法是跳過元素。因此,您可以找到要排除的元素的結束位置,並且在該位置之前您不會處理任何其他內容:

final ArrayList<String> excludeTags = new ArrayList<String>(Arrays.asList(new String[] {"head", "script", "a"})); 
final ArrayList<String> excludeClasses = new ArrayList<String>(Arrays.asList(new String[] {"noProcess"})); 

Source.LegacyIteratorCompatabilityMode = true; 
Source source = new Source(htmlToProcess); 
OutputDocument outputDocument = new OutputDocument(source); 

int skipToPos = 0; 
for (Segment segment : source) { 
    if (segment.getBegin() >= skipToPos) { 
     if (segment instanceof Tag) { 
      Tag tag = (Tag) segment; 
      Element element = tag.getElement(); 

      // check excludeTags 
      if (excludeTags.contains(tag.getName().toLowerCase())) { 
       skipToPos = element.getEnd(); 
      } 

      // check excludeClasses 
      String classes = element.getAttributeValue("class"); 
      if (classes != null) { 
       for (String theClass : classes.split(" ")) { 
        if (excludeClasses.contains(theClass.toLowerCase())) { 
         skipToPos = element.getEnd(); 
        } 
       } 
      } 

     } else if (segment instanceof CharacterReference) { // for future use. Source.LegacyIteratorCompatabilityMode = true; 
      CharacterReference characterReference = (CharacterReference) segment; 
     } else { 
      outputDocument.replace(segment, doProcessText(segment.toString())); 
     } 
    } 
} 

return outputDocument.toString();