使用Java解析HTML数据(DOM解析)
我已经研究了一段时间,并没有找到任何与Stack Overflow相关的东西。 我正在使用一个旨在捕获HTML代码片段的解析器。 基于代码(下面进一步说明),文件的大小呈指数级增长并且正在捕获我需要的字段(li),但也是非常重复的,因为它一遍又一遍地捕获相同的数据。
这是我正在阅读的文件(完整文件实际上有超过100行但这里只包括3行):
Name: J0719 Description: - Hop Counts: 2
- State: 3
Name: J0716 Description: - Hop Counts: 3
- State: 2
Name: J0718 Description: - Hop Counts: 1
- State: 5
Name: J0726 Description: - Hop Counts: 8
- State: 4
我的完整代码在这里:
package ReadXMLFile_part2; import java.io.*; import org.jsoup.Jsoup; import org.jsoup.select.Elements; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import java.util.Enumeration; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.text.MutableAttributeSet; import javax.swing.text.html.HTML.Tag; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.parser.ParserDelegator; public class ReadXMLFile_part2 { public static void main(String[] args) throws Exception { PrintStream out = new PrintStream(new FileOutputStream("C:/XML_UltraEdit/XML_Sandbox/NetBeans_Java_Project/results2.xml")); System.setOut(out); System.out.println("*** JSOUP ***"); File input = new File("C:/XML_UltraEdit/XML_Sandbox/NetBeans_Java_Project/output2_TEST.html"); Document doc = null; try { doc = Jsoup.parse(input,"UTF-8", "http://www.w3.org/1999/xhtml" ); } catch (IOException ex) { Logger.getLogger(ReadXMLFile_part2.class.getName()).log(Level.SEVERE, null, ex); } BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); //For loops to capture the fields in the file Element bracket = doc.getElementsByTag("bracket").first(); Elements trs = bracket.getElementsByTag("description"); for (Element description : trs) { for (Element li : description.getAllElements()) { System.out.println(li.text()); } } System.out.println(); //read a line from the console String lineFromInput = in.readLine(); //output to the file a line out.println(lineFromInput); out.close(); } }
我的问题是如何解析输入文件中标有“li”的字段,以便我的输出文件为每个“li”标记都有一个新行。 理想的输出将是这样(并防止无限循环):
Name: J0719 Hop Counts: 2 State: 3 Name: J0716 Hop Counts: 3 State: 2 Name: J0718 Hop Counts: 1 State: 5 Name: J0726 Hop Counts: 8 State: 4
感谢并感谢任何帮助!
9月2日更新:虽然previousElementSibling在单独使用时很有用,但是当我还试图拉出“描述”字段时,我需要另一种类型的嵌套循环(否则previousElementSibling每次都连续拉动第一个前一个元素)。 我发现更快的解决方法是只更改原始代码中的标记,使其现在看起来像下面的代码:
更新的XML文件:
Name: J0719 Description: - Hop Counts 2
- State: 3
- Name: J0716
Description: - Hop Counts 3
- State: 2
- Name: J0718
Description: - Hop Counts 1
- State: 5
- Name: J0719
Description: - Hop Counts 8
- State: 4
除了以下’for’循环之外,原始代码中的所有其他内容保持不变
//Updated Code: //For loops to capture the (li) fields in the file Elements brackets = doc.getElementsByTag("bracket"); for (Element bracket : brackets) { Elements lis = bracket.select("li"); for (Element li : lis){ System.out.println(li.text()); } break; } System.out.println();
唯一的另一件事是,在我看到文件大小停止增长后,我必须在执行后稍后手动按下“停止”运行按钮。 但我仍然看到输出文件产生了预期的结果。
如果我正确地理解了您的问题,那么您就难以理解xml中的name
和bracket
节点不是父节点的子节点,而是相互追随。 我认为在拥有bracket
元素时获取正确name
元素的解决方案是使用JSOUP的DOM导航方法 ,即previousElementSibling()
这是你的循环看起来像:
Elements brackets = doc.getElementsByTag("bracket"); for (Element bracket : brackets) { Element lis = bracket.select("li"); Element name = bracket.previousElementSibling(); System.out.println(name.text()); for (Element li : lis){ System.out.println(li.text()); } }