2013-06-27 59 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();