Я решил использовать этот синтаксический анализатор как зависимость от maven
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>
<version>2.1</version>
</dependency>
Я вызвал синтаксический анализатор SAX следующим образом:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class TestHTML {
public static void main(String[] args) throws IOException, SAXException {
org.xml.sax.XMLReader reader = org.xml.sax.helpers.XMLReaderFactory.createXMLReader("org.htmlparser.sax.XMLReader");
HTMLTableContentHandler htmlTableContentHandler = new HTMLTableContentHandler();
reader.setContentHandler(htmlTableContentHandler);
String userDir = System.getProperty("user.home");
byte[] contents = Files.readAllBytes(Paths.get(userDir, "test.html"));
reader.parse(new InputSource(new ByteArrayInputStream(contents)));
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(new JTable(htmlTableContentHandler.getRowData(), htmlTableContentHandler.getColumnNames())));
frame.pack();
frame.setVisible(true);
});
}
}
Обработчик содержимого заполняет массивы для JTable по мере его проходит через SAX-события:
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class HTMLTableContentHandler extends DefaultHandler {
private List<Object> columnNames = new ArrayList<>();
private List<Object[]> rowData = new ArrayList<>();
private StringBuilder content = new StringBuilder();
private int rowIndex;
private int colIndex;
private boolean readingColumnName;
private boolean readingCell;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("B".equals(localName) && rowIndex == 0) {
if (readingColumnName) {
columnNames.add(content.toString().trim());
readingColumnName = false;
} else {
readingColumnName = true;
}
}
if ("TD".equals(localName) && rowIndex > 0) {
readingCell = true;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (readingColumnName || readingCell) {
content.append(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("TR".equals(localName)) {
rowIndex++;
colIndex = 0;
}
if ("TD".equals(localName) && rowIndex > 0) {
if (colIndex == 0) {
rowData.add(new Object[columnNames.size()]);
}
rowData.get(rowIndex - 1)[colIndex++] = content.toString().trim();
readingCell = false;
}
content.setLength(0);
}
public Object[] getColumnNames() {
return columnNames.toArray();
}
public Object[][] getRowData() {
return rowData.toArray(new Object[0][]);
}
}