我有一个字符串输入,我需要从中提取简单信息,这里是示例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
我做错了什么?
Addon:
这是我的主要方法:
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);
}
答案 0 :(得分:48)
您应该使用以下内容替换saxParser.parse(xml.toString(), handler);
行:
saxParser.parse(new InputSource(new StringReader(xml)), handler);
答案 1 :(得分:2)
我要强调另一个问题,一旦你正确阅读文件,你可能会遇到这个问题。
方法
public void characters(char ch[], int start, int length)
并不总能为您提供完整的文字元素。您可以自由地一次为您提供文本元素(内容)'n'字符。来自the doc:
SAX解析器可以在单个中返回所有连续的字符数据 块,或者他们可能将它分成几个块
因此,您应该在每次调用此方法时构建文本元素字符串(例如,使用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();
}
答案 2 :(得分:1)
Mybe这个帮助。它使用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遍历文档,并按名称
检查每个节点答案 3 :(得分:0)
似乎你从here获取了这个例子。您需要将带有绝对路径而不是字符串的文件传递给方法SAXParser.parse()
;仔细看一下这个例子。方法parse()
defined as遵循
public void parse(File f,
DefaultHandler dh)
throws SAXException,
IOException
如果你想解析一个字符串。还有另一种方法需要Inputstream
。
public void parse(InputStream is,
DefaultHandler dh)
throws SAXException,
IOException
然后你需要将你的字符串转换为InputStream 。这是how to do it。
答案 4 :(得分:0)
您使用String
作为第一个参数调用解析。根据{{3}},该字符串被解释为您文件的URI
。
如果您想直接解析String
,则必须首先将其转换为InputStream
,以便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);