将String转换为XML文档时出现致命错误

时间:2013-06-06 09:18:19

标签: java xml parsing xml-parsing fatal-error

我有String数据的XML数据,我想将其转换为XML文档,以便在其中进行一些处理,并且我使用以下方法来实现:

private Document convert(String xml) throws ParserConfigurationException,
            SAXException, IOException {

        // convert String into InputStream
        InputStream is = new ByteArrayInputStream(xml.getBytes());

        // convert InputStream to Document
        domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true);
        builder = domFactory.newDocumentBuilder();
        builder(builder); // this is the error handler method i'm using
        Document doc = builder.parse(is);
        is.close();

        return doc;
    }

奇怪的是,处理过程正确完成并且每件事情都很完美我的结果,但另一方面,当我进行转换过程时,我在控制台中收到了一条消息:

[Fatal Error] :1:1: Premature end of file.

所以,我使用了一个错误处理程序来捕获该致命错误并打印异常堆栈跟踪,然后我抛出了这些异常:

org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
    at com.nc.inotify.dp.xml.impl.XmlSource.convert(XmlSource.java:327)
    at com.nc.inotify.dp.xml.impl.XmlSource.update(XmlSource.java:299)
    at com.nc.inotify.dp.xml.junit.TXmlSource.testUpdate(TXmlSource.java:106)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

更新 XML文件:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<rss xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" version="2.0">
            <channel>

<title>Yahoo! Weather - Sunnyvale, CA</title>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/Sunnyvale__CA/*http://weather.yahoo.com/forecast/USCA1116_f.html</link>
<description>Yahoo! Weather for Sunnyvale, CA</description>
<language>en-us</language>
<lastBuildDate>Thu, 06 Jun 2013 1:56 am PDT</lastBuildDate>
<ttl>60</ttl>
<yweather:location city="Sunnyvale" country="United States" region="CA"/>
<yweather:units distance="mi" pressure="in" speed="mph" temperature="F"/>
<yweather:wind chill="58" direction="30" speed="3"/>
<yweather:atmosphere humidity="81" pressure="29.96" rising="2" visibility="10"/>
<yweather:astronomy sunrise="5:46 am" sunset="8:25 pm"/>
<image>
<title>Yahoo! Weather</title>
<width>142</width>
<height>18</height>
<link>http://weather.yahoo.com</link>
<url>http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif</url>
</image>
<item>
<title>Conditions for Sunnyvale, CA at 1:56 am PDT</title>
<geo:lat>37.37</geo:lat>
<geo:long>-122.04</geo:long>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/Sunnyvale__CA/*http://weather.yahoo.com/forecast/USCA1116_f.html</link>
<pubDate>Thu, 06 Jun 2013 1:56 am PDT</pubDate>
<yweather:condition code="26" date="Thu, 06 Jun 2013 1:56 am PDT" temp="58" text="Cloudy"/>
<description><![CDATA[
<img src="http://l.yimg.com/a/i/us/we/52/26.gif"/><br />
<b>Current Conditions:</b><br />
Cloudy, 58 F<BR />
<BR /><b>Forecast:</b><BR />
Wed - Partly Cloudy. High: 70 Low: 55<br />
Thu - AM Clouds/PM Sun. High: 74 Low: 57<br />
Fri - Partly Cloudy. High: 81 Low: 62<br />
Sat - Sunny. High: 78 Low: 63<br />
Sun - Partly Cloudy. High: 72 Low: 60<br />
<br />
<a href="http://us.rd.yahoo.com/dailynews/rss/weather/Sunnyvale__CA/*http://weather.yahoo.com/forecast/USCA1116_f.html">Full Forecast at Yahoo! Weather</a><BR/><BR/>
(provided by <a href="http://www.weather.com" >The Weather Channel</a>)<br/>
]]></description>
<yweather:forecast code="29" date="5 Jun 2013" day="Wed" high="70" low="55" text="Partly Cloudy"/>
<yweather:forecast code="30" date="6 Jun 2013" day="Thu" high="74" low="57" text="AM Clouds/PM Sun"/>
<yweather:forecast code="30" date="7 Jun 2013" day="Fri" high="81" low="62" text="Partly Cloudy"/>
<yweather:forecast code="32" date="8 Jun 2013" day="Sat" high="78" low="63" text="Sunny"/>
<yweather:forecast code="30" date="9 Jun 2013" day="Sun" high="72" low="60" text="Partly Cloudy"/>
<guid isPermaLink="false">USCA1116_2013_06_09_7_00_PDT</guid>
</item>
</channel>
</rss><!-- api10.weather.ch1.yahoo.com Thu Jun  6 09:34:11 PST 2013 -->

2 个答案:

答案 0 :(得分:0)

如何通过创建一个单独的类来使这个私有方法可测试?让我们从测试开始:

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;

import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class StringToDOMConverterTest {

private StringToDOMConverter stringToDOMConverter = new StringToDOMConverter();

@Test
public void converterShouldConvertSimpleDocument() throws Exception {
    final Document dom = stringToDOMConverter.convert("<mail><to>Alice</to><from>Jum</from><heading>Invitation</heading><body>Let's get some icecream!</body></mail>");
    final Element documentRoot = dom.getDocumentElement();
    assertThat(documentRoot.getNodeName(), is("mail"));
}
}

现在是方法的修改版本(构建器语句未编译):

    import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class StringToDOMConverter {

private final DocumentBuilderFactory domFactory;
private DocumentBuilder builder;

public StringToDOMConverter() {
    domFactory = DocumentBuilderFactory.newInstance();
    domFactory.setNamespaceAware(false);
}

public Document convert(final String xml) throws ParserConfigurationException, SAXException, IOException {

    final InputStream is = new ByteArrayInputStream(xml.getBytes());
    Document document = null;
    try {
        builder = domFactory.newDocumentBuilder();
        // builder(builder); // this is the error handler method i'm using
        document = builder.parse(is);
    } finally {
        if(is != null)  is.close();
    }
    return document;
}
}

这是一个可以尝试所有标志和错误处理内容的基础。不要忘记需要检查前置条件并适当地处理错误(并为此编写测试... :-))。

答案 1 :(得分:0)

您的xml不是格式良好的xml。如果您在浏览器中打开它,您可以看到它没有正确打开。您可以使用以下位置提供的xml验证程序验证xml:

http://www.w3schools.com/xml/xml_validator.asp

修复你的xml,你应该很好。