当 xml 输入作为流给出并且某些 xml 元素为空时,SAX 解析器无法正常工作
SAX parser is not working properly when xml input is given as stream and some xml elements are empty
当 xml 输入作为输入流提供给 SAX 解析器且某些 xml 元素为空时,则
解析器的字符方法未被调用并得到不同的结果。
例如,
XML 输入:
<root>
<salutation>Hello Sir</salutation>
<userName />
<parent>
<child>a</child>
</parent>
<parent>
<child>b</child>
</parent>
<parent>
<child>c</child>
</parent>
<success>yes</success>
<hoursSpent />
</root>
解析器实现:
public class MyContentHandler implements ContentHandler {
private String salutation;
private String userName;
private String success;
private String hoursSpent;
String tmpValue="";
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("salutation".equals(qName)) {
userName=tmpValue;
}
}else
if ("userName".equals(qName)) {
userName=tmpValue;
}
}else
if ("success".equals(qName)) {
success=tmpValue;
}
}else
if ("hoursSpent".equals(qName)) {
hoursSpent=tmpValue;
}
}
public void characters(char[] ch, int begin, int length) throws SAXException {
tmpValue = new String(ch, begin, length).trim();
}
主程序:
public class MainProgram{
public static void main(String[] args) throws Exception {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
MyContentHandler contentHandler = new MyContentHandler(xmlReader);
xmlReader.setContentHandler(contentHandler);
String input = "<root><salutation>Hello Sir</salutation><userName /><parent><child>a</child></parent><parent><child>b</child></parent><success>yes</success><hoursSpent /></root>";
InputStream stream = new ByteArrayInputStream(input.getBytes());
xmlReader.parse(new InputSource(stream));
System.out.println(contentHandler.getUserName()); //prints Hello sir instead of null
System.out.println(contentHandler.getHoursSpent); //prints yes instead of null
如果指定的空 xml 元素没有打开和关闭元素,如下所示,
<userName />
而不是 <userName></userName>
,那么处理程序 class 中的 character() 方法不会被执行,并且设置了错误的值。仅当我使用输入 xml 作为输入流时才会出现此问题。请帮我解决这个问题
解析器的行为完全符合规定,是您的代码有误。
通常,解析器在开始标记和相应的结束标记之间对 characters()
方法进行零对多调用。您需要在 startElement() 中初始化一个空缓冲区,在 characters() 中附加到缓冲区,然后在 endElement() 中使用累加值。
按照您的编写方式,您不仅会得到一个空元素的错误结果,而且如果解析器将文本分成多个调用,您也会得到错误的结果,如果 (a)文本中存在实体引用,或者 (b) 文本很长,或者 (c) 文本恰好跨越两个块,这两个块是在单独的 read() 调用中从输入流中读取的。
当 xml 输入作为输入流提供给 SAX 解析器且某些 xml 元素为空时,则 解析器的字符方法未被调用并得到不同的结果。
例如,
XML 输入:
<root>
<salutation>Hello Sir</salutation>
<userName />
<parent>
<child>a</child>
</parent>
<parent>
<child>b</child>
</parent>
<parent>
<child>c</child>
</parent>
<success>yes</success>
<hoursSpent />
</root>
解析器实现:
public class MyContentHandler implements ContentHandler {
private String salutation;
private String userName;
private String success;
private String hoursSpent;
String tmpValue="";
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("salutation".equals(qName)) {
userName=tmpValue;
}
}else
if ("userName".equals(qName)) {
userName=tmpValue;
}
}else
if ("success".equals(qName)) {
success=tmpValue;
}
}else
if ("hoursSpent".equals(qName)) {
hoursSpent=tmpValue;
}
}
public void characters(char[] ch, int begin, int length) throws SAXException {
tmpValue = new String(ch, begin, length).trim();
}
主程序:
public class MainProgram{
public static void main(String[] args) throws Exception {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
MyContentHandler contentHandler = new MyContentHandler(xmlReader);
xmlReader.setContentHandler(contentHandler);
String input = "<root><salutation>Hello Sir</salutation><userName /><parent><child>a</child></parent><parent><child>b</child></parent><success>yes</success><hoursSpent /></root>";
InputStream stream = new ByteArrayInputStream(input.getBytes());
xmlReader.parse(new InputSource(stream));
System.out.println(contentHandler.getUserName()); //prints Hello sir instead of null
System.out.println(contentHandler.getHoursSpent); //prints yes instead of null
如果指定的空 xml 元素没有打开和关闭元素,如下所示,
<userName />
而不是 <userName></userName>
,那么处理程序 class 中的 character() 方法不会被执行,并且设置了错误的值。仅当我使用输入 xml 作为输入流时才会出现此问题。请帮我解决这个问题
解析器的行为完全符合规定,是您的代码有误。
通常,解析器在开始标记和相应的结束标记之间对 characters()
方法进行零对多调用。您需要在 startElement() 中初始化一个空缓冲区,在 characters() 中附加到缓冲区,然后在 endElement() 中使用累加值。
按照您的编写方式,您不仅会得到一个空元素的错误结果,而且如果解析器将文本分成多个调用,您也会得到错误的结果,如果 (a)文本中存在实体引用,或者 (b) 文本很长,或者 (c) 文本恰好跨越两个块,这两个块是在单独的 read() 调用中从输入流中读取的。