【问题标题】:How do I load an HTML table to a swing JTable?如何将 HTML 表格加载到摇摆 JTable?
【发布时间】:2020-11-01 22:43:03
【问题描述】:

HTML 表格输入没有表格标题的 TH,而是带有粗体文本的 TD

看起来像这样:

<html>
<body>
<table>
<tr>
<td>
<b>column1</b>
</td>
<td>
<b>column2</b>
</td>
<td>
<b>column3</b>
</td>
</tr><tr>
<td>
value1
</td>
<td>
value2
</td>
<td>
value3
</td>
</tr>
</table>
</html>

因此,我希望将 HTML 表格标题作为 JTable 列处理,并将第一个表格行之后的其他 TD 处理为 JTable 单元格。

【问题讨论】:

    标签: java html swing parsing sax


    【解决方案1】:

    我选择将此解析器用作 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);
            });
        }
    }
    

    内容处理程序在处理 SAX 事件时填充 JTable 的数组:

    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][]);
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果您想使用 JDK 的标准类,您可以执行以下操作:

      import java.io.*;
      import java.net.*;
      import java.util.*;
      import javax.swing.*;
      import javax.swing.table.*;
      import javax.swing.text.*;
      import javax.swing.text.html.*;
      import javax.swing.text.html.parser.*;
      
      public class ParserCallbackTable extends HTMLEditorKit.ParserCallback
      {
          private boolean tableFound = false;
      
          private Vector<Object> columnNames;
          private Vector<Vector<Object>> data = new Vector<Vector<Object>>();
      
          private Vector<Object> row;
      
          public ParserCallbackTable(String uri)
          {
              try
              {
                  Reader reader = getReader( uri );
                  new ParserDelegator().parse(reader, this, true);
              }
              catch(Exception e)
              {
                  e.printStackTrace();
              }
          }
      
          public void handleStartTag(HTML.Tag tag, MutableAttributeSet a, int pos)
          {
              if ("table".equals(tag.toString()))
                  tableFound = true;
      
              if ("tr".equals(tag.toString()))
                  row = new Vector<Object>();
          }
      
          public void handleEndTag(HTML.Tag tag, int pos)
          {
              if ("table".equals(tag.toString()))
                  tableFound = false;
      
              if ("tr".equals(tag.toString()))
              {
                  if (columnNames == null) // first row of data is the column names
                      columnNames = row;
                  else
                      data.add( row );
              }
          }
      
          public void handleText(char[] data, int pos)
          {
              if (tableFound)
                  row.add( new String(data) );
          }
      
          public TableModel getModel()
          {
              return new DefaultTableModel(data, columnNames);
          }
      
          private Reader getReader(String uri) throws IOException
          {
              if (uri.startsWith("http")) // Retrieve from Internet
              {
                  URLConnection conn = new URL(uri).openConnection();
                  return new InputStreamReader(conn.getInputStream());
              }
              else // Retrieve from file
              {
                  return new FileReader(uri);
              }
          }
      
          public static void main(String[] args) throws IOException
          {
              ParserCallbackTable parser = new ParserCallbackTable( args[0] );
              JTable table = new JTable( parser.getModel() );
      
              JFrame frame = new JFrame("HTML to JTable");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.add( new JScrollPane(table) );
              frame.pack();
              frame.setLocationByPlatform( true );
              frame.setVisible( true );
          }
      }
      

      只需传递您的 HTML 文件的名称即可进行快速测试。例如:

      java ParserCallbackTable table.html
      

      【讨论】:

      • 不需要在 handleText() 中附加到 StringBuilder 吗?它会立即接收整个文本?
      猜你喜欢
      • 1970-01-01
      • 2014-05-22
      • 2015-01-11
      • 1970-01-01
      • 1970-01-01
      • 2017-07-29
      • 1970-01-01
      • 2012-02-29
      • 2012-07-23
      相关资源
      最近更新 更多