【问题标题】:How XML parsing works Inside SAX Parser?XML 解析如何在 SAX 解析器中工作?
【发布时间】:2019-03-10 16:51:28
【问题描述】:

我正在尝试使用 SAX 解析 XML。下面是一段代码sn-p:

public class ReadXML {

   public static void main(String argv[]) {

    try {

    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser saxParser = factory.newSAXParser();

    DefaultHandler handler = new DefaultHandler() {

    boolean bfname = false;
    boolean blname = false;
    boolean bnname = false;
    boolean bsalary = false;

    public void startElement(String uri, String localName,String qName, 
                Attributes attributes) throws SAXException {

        System.out.println("Parameters :" + uri +":"+ localName +":"+ qName +":"+ attributes);
        System.out.println("Start Element :" + qName);

        if (qName.equalsIgnoreCase("FIRSTNAME")) {
            bfname = true;
        }

        if (qName.equalsIgnoreCase("LASTNAME")) {
            blname = true;
        }

        if (qName.equalsIgnoreCase("NICKNAME")) {
            bnname = true;
        }

        if (qName.equalsIgnoreCase("SALARY")) {
            bsalary = true;
        }

    }

    public void endElement(String uri, String localName,
        String qName) throws SAXException {

        System.out.println("End Element :" + qName);

    }

    public void characters(char[] ch, int start, int length) throws SAXException {

        System.out.println("Im here:"+Arrays.toString(ch));
        if (bfname) {
            System.out.println("First Name : " + new String(ch, start, length));
            bfname = false;
        }

        if (blname) {
            System.out.println("Last Name : " + new String(ch, start, length));
            blname = false;
        }

        if (bnname) {
            System.out.println("Nick Name : " + new String(ch, start, length));
            bnname = false;
        }

        if (bsalary) {
            System.out.println("Salary : " + new String(ch, start, length));
            bsalary = false;
        }

    }

     };

       saxParser.parse("C:\\Lenny\\Work\\XML\\SaxParsing_01.xml", handler); --(1)


     } catch (Exception e) {
       e.printStackTrace();
     }

   }

}

我的第一个问题是,当代码到达 saxParser.parse("C:\\Ashish\\Work\\XML\\SaxParsing_01.xml", handler); 时,会调用以下两个方法..!

    public void parse(File f, HandlerBase hb)
            throws SAXException, IOException {
            if (f == null) {
                throw new IllegalArgumentException("File cannot be null");
            }

            String escapedURI = FilePathToURI.filepath2URI(f.getAbsolutePath());
            if (DEBUG) {
                System.out.println("Escaped URI = " + escapedURI);
            }
            InputSource input = new InputSource(escapedURI);
            this.parse(input, hb);
        }

public void parse(InputSource is, DefaultHandler dh)
        throws SAXException, IOException {
        if (is == null) {
            throw new IllegalArgumentException("InputSource cannot be null");
        }
        XMLReader reader = this.getXMLReader();
        if (dh != null) {
            reader.setContentHandler(dh);
            reader.setEntityResolver(dh);
            reader.setErrorHandler(dh);
            reader.setDTDHandler(dh);
        }
        reader.parse(is);
    }

很想知道,当reader.parse(is) 被调用时,内部会发生什么?我唯一的假设是,reader 正在读取 XML 并将上述代码中创建的 DefautHandler 数据结构放入并相应地生成输出。

我尝试了很多方法来查找parse(is) 方法的源代码,但找不到。在 SAXParser 类中,parse 是一个抽象方法,因此无法找到实现类,我可以在其中查看源代码以进一步了解。

第二个但很愚蠢的问题,请问,当我们创建DefautHandler 实例时,该块内的方法是否被覆盖?在构造函数块中,我们是否允许像创建四个布尔变量一样创建变量?在 Java 中从未见过这种方法。

任何人都可以帮助我吗......?

谢谢

【问题讨论】:

    标签: java xml sax


    【解决方案1】:

    SAXParser 是一个接口,并且有许多 XML 解析器实现了这个接口。如果您想知道它是如何工作的,您需要选择这些 XML 解析器之一 - 最容易访问的是 Apache Xerces 解析器。你可以从这里开始,但要注意这并不容易阅读:

    https://apache.googlesource.com/xerces2-j/+/f59f47412e404f4984480a45a99957ac07d287d4/src/org/apache/xerces/parsers/AbstractSAXParser.java

    简单来说,解析器会寻找一个“ContentHandler的startElement()方法。

    您实际上并不需要了解它在内部是如何工作的,才能成功使用 SAX 解析器,尽管尝试一下做得很好。

    您说得对,编写 SAX ContentHandler(可能作为 DefaultHandler 的扩展)涉及一种与您可能习惯的完全不同的 Java 编程风格。因为您的代码通过回调处理事件,所以您无法像拥有主控制循环那样维护堆栈上的当前状态。相反,您必须考虑对诸如 startElement() 或 characters() 之类的方法的每次调用如何影响应用程序需要维护的当前状态,并弄清楚如何修改保持此状态的数据结构。这是一种完全不同的编程方式,也是有人说“拉”解析接口比“推”接口更容易使用的原因之一。

    【讨论】:

      猜你喜欢
      • 2011-06-17
      • 2012-08-27
      • 1970-01-01
      • 2011-05-31
      • 1970-01-01
      • 2011-04-30
      • 2017-07-27
      • 2011-05-26
      • 1970-01-01
      相关资源
      最近更新 更多