11

我有一个字符串输入,我需要从中提取简单信息,这是示例 xml(来自 mkyong):

<?xml version="1.0"?>
<company>
    <staff>
        <firstname>yong</firstname>
        <lastname>mook kim</lastname>
        <nickname>mkyong</nickname>
        <salary>100000</salary>
    </staff>
    <staff>
        <firstname>low</firstname>
        <lastname>yin fong</lastname>
        <nickname>fong fong</nickname>
        <salary>200000</salary>
    </staff>
</company>

我如何在我的代码中解析它(我的String name类中有一个字段):

public String getNameFromXml(String xml) {
        try {

            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();
            DefaultHandler handler = new DefaultHandler() {

                boolean firstName = false;

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

                    if (qName.equalsIgnoreCase("firstname")) {
                        firstName = true;
                    }
                }

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

                    if (firstName) {
                        name = new String(ch, start, length);
                        System.out.println("First name is : " + name);
                        firstName = false;
                    }

                }

            };

            saxParser.parse(xml.toString(), handler);

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

        return name;
    }

我得到一个java.io.FileNotFoundException,我看到它正在尝试查找文件myprojectpath + the entireStringXML

我究竟做错了什么?

添加在 :

这是我的主要方法:

public static void main(String[] args) {
        Text tst = new Text("<?xml version=\"1.0\"?><company>   <staff>     <firstname>yong</firstname>     <lastname>mook kim</lastname>       <nickname>mkyong</nickname>     <salary>100000</salary> </staff>    <staff>     <firstname>low</firstname>      <lastname>yin fong</lastname>       <nickname>fong fong</nickname>      <salary>200000</salary> </staff></company>");
        NameFilter cc = new NameFilter();
        String result = cc.getNameFromXml(tst);
        System.out.println(result);
    }
4

5 回答 5

50

您应该使用saxParser.parse(xml.toString(), handler);以下行替换该行:

saxParser.parse(new InputSource(new StringReader(xml)), handler);
于 2012-06-25T15:25:05.513 回答
2

我将强调另一个问题,一旦你正确阅读了你的文件,你可能会遇到这个问题。

方法

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

不会总是给你完整的文本元素。一次给你文本元素(内容)'n'个字符是自由的。从文档

SAX 解析器可以在单个块中返回所有连续的字符数据,也可以将其拆分为多个块

因此,您应该从每次调用此方法(例如使用 a )构建您的文本元素字符串,并且仅在调用相应方法StringBuilder后解释/存储该文本。endElement()

现在这可能不会影响您。但它会在未来的某个时间出现——可能是你最不期待的时候。我在从小型 XML 文档移动到大型 XML 文档时遇到过这种情况,其中缓冲能够容纳整个小文档,但不能容纳较大的文档。

一个例子(伪代码):

   public void startElement() {
      builder.clear();
   }
   public void characters(char ch[], int start, int length) {
      builder.append(new String(ch, start, length));
   }
   public void endElement() {
      // no do something with the collated text
      builder.toString();
   }
于 2012-06-25T15:39:05.780 回答
1

我的这个帮助。它使用 javax.xml.parsers.DocumentBuilder,这比 SAX 更容易

public Document getDomElement(String xml){
        Document doc = null;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {

            DocumentBuilder db = dbf.newDocumentBuilder();

            InputSource is = new InputSource();
                is.setCharacterStream(new StringReader(xml));
                doc = db.parse(is); 

            } catch (ParserConfigurationException e) {
                Log.e("Error: ", e.getMessage());
                return null;
            } catch (SAXException e) {
                Log.e("Error: ", e.getMessage());
                return null;
            } catch (IOException e) {
                Log.e("Error: ", e.getMessage());
                return null;
            }
                // return DOM
            return doc;
    }

您可以使用 NodeList 遍历文档并按其名称检查每个节点

于 2012-06-25T15:21:40.037 回答
0

String您使用 a作为第一个参数调用 parse 。根据文档,该字符串被解释为URI您的文件。

如果您想String直接解析您的,您必须首先将其转换为 anInputStream以便与parse(InputSource is, DefaultHandler dh)方法(docu)一起使用:

// transform from string to inputstream
ByteArrayInputStream in = new ByteArrayInputStream(xml.toString().getBytes());
InputSource is = new InputSource();
is.setByteStream(in);

// start parsing
saxParser.parse(xml.toString(), handler);
于 2012-06-25T15:26:11.877 回答
0

似乎你从这里拿了这个例子。您需要将具有绝对路径的文件而不是字符串传递给方法SAXParser.parse();仔细看这个例子。方法parse() 定义如下

public void parse(File f,
                  DefaultHandler dh)
           throws SAXException,
                  IOException

如果你想解析一个字符串。还有另一种方法Inputstream

public void parse(InputStream is,
                  DefaultHandler dh)
           throws SAXException,
                  IOException

然后您需要将您的字符串转换为 InputStream。这是如何做到的

于 2012-06-25T15:24:00.910 回答