我正在尝试解析XML response
,但我失败了。我最初想过
xml
刚刚没有在回复中返回,所以我通过在线直接链接到我的xml
文件来制作下面的代码。我能够毫无问题地将XML
打印到屏幕上。但是,当我调用我的解析方法时,我得到文件过早结束。
如果我直接传递URL,它会起作用:
但是当我传递一个InputStream时失败了:
builder.parse(connection.getInputStream());
try {
URL url = new URL(xml);
URLConnection uc = url.openConnection();
HttpURLConnection connection = (HttpURLConnection )uc;
connection.setDoInput(true);
connection.setDoOutput(true);
InputStream instream;
InputSource source;
//get XML from InputStream
if(connection.getResponseCode()>= 200){
connection.connect();
instream = connection.getInputStream();
parseDoc(instream);
}
else{
instream = connection.getErrorStream();
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
static void parseDoc(InputStream instream) throws ParserConfigurationException,
SAXException, IOException{
BufferedReader buff_read = new BufferedReader(new InputStreamReader(instream,"UTF-8"));
String inputLine = null;
while((inputLine = buff_read.readLine())!= null){
System.out.println(inputLine);
}
DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();
factory.isIgnoringElementContentWhitespace();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(instream);
}
我得到的错误:
[Fatal Error] :1:1: Premature end of file.
org.xml.sax.SAXParseException: Premature end of file.
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.ameba.api.network.MainApp.parseDoc(MainApp.java:78)
at com.ameba.api.network.MainApp.main(MainApp.java:41)
答案 0 :(得分:28)
当你这样做时,
while((inputLine = buff_read.readLine())!= null){
System.out.println(inputLine);
}
你在instream中消耗所有东西,所以instream是空的。现在尝试这样做时,
Document doc = builder.parse(instream);
解析将失败,因为您已经传递了一个空流。
答案 1 :(得分:3)
您收到错误是因为SAXBuilder不够智能,无法处理“空白状态”。因此它至少会查找<xml ..>
声明,当它导致无数据响应时,它会创建您看到的异常,而不是报告空状态。
答案 2 :(得分:2)
对于那些到达这篇文章的答案:
这主要是因为DOM解析器消耗的InputStream
为空
因此,在我遇到的情况中,可能有两种情况:
File
已被使用并因此被清空。InputStream
或您创建InputStream
的任何内容可能是空文件或字符串或其他内容。空虚可能是导致问题的原因。因此,您需要检查protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
List<MyDataType> dataList = null;
try {
dataList = ***;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HashMap<String, List<BigDecimal>> recordYearlyData = new HashMap<>();
String nwC = "New Customers ";
String alC = "All Customers ";
String lsC = "Lost Customers ";
String rtC = "Rate ";
List<BigDecimal> startCus = new ArrayList<>();
List<BigDecimal> newCus = new ArrayList<>();
List<BigDecimal> endCus = new ArrayList<>();
List<BigDecimal> thisYearCus = new ArrayList<>();
List<BigDecimal> lostCus = new ArrayList<>();
List<BigDecimal> rateL = new ArrayList<>();
for (MyDataType dataType : dataList) {
String createDate = dataType.getOrderDate().toString();
String createDateN = createDate.substring(5, 7);
Integer getDateKey = Integer.parseInt(createDateN) - 1;
Integer getYear = Integer.parseInt(createDate.substring(0,4));
BigDecimal tenant_id = dataType.getTenantID();
createDateLabel = monthNames[getDateKey];
if (getYear != yearChecker) {
String yearLabel = String.valueOf(getYear - 1);
for (BigDecimal tenant : thisYearCus) {
if (newCus.contains(tenant) || startCus.contains(tenant)) {
endCus.add(tenant);
}
}
for (BigDecimal tenant : startCus) {
if (!thisYearCus.contains(tenant)) {
lostCus.add(tenant);
}
}
double rate = 1.0;
if (startCus.size() == 0) {
rate=1.0;
} else if (startCus.size() > 0){
rate = ((double) endCus.size() - (double) newCus.size())/(double) startCus.size();
}
rateL.add(BigDecimal.valueOf(rate));
recordYearlyData.put(alC+yearLabel, thisYearCus);
recordYearlyData.put(nwC+yearLabel, newCus);
recordYearlyData.put(lsC+yearLabel, lostCus);
recordYearlyData.put(rtC+yearLabel, rateL);
rateL.clear();
startCus.clear();
startCus.addAll(thisYearCus);
thisYearCus.clear();
endCus.clear();
newCus.clear();
lostCus.clear();
yearChecker = getYear;
}
if (!thisYearCus.contains(tenant_id)) {
thisYearCus.add(tenant_id);
}
if (!startCus.contains(tenant_id)) {
if(!newCus.contains(tenant_id)) {
newCus.add(tenant_id);
}
}
}
request.setAttribute("newCusTable", recordYearlyData.get("New Customers 2015"));
request.setAttribute("allCusTable", recordYearlyData.get("All Customers 2015"));
request.setAttribute("lostCusTable", recordYearlyData.get("Lost Customers 2015"));
request.setAttribute("retRate", recordYearlyData.get("Rate 2015"));
RequestDispatcher view = request.getRequestDispatcher("/Sales.jsp");
view.forward(request, response);
}
。答案 3 :(得分:1)
我遇到了同样的错误,可以通过记录异常轻松找到问题所在:
documentBuilder.setErrorHandler(new ErrorHandler() {
@Override
public void warning(SAXParseException exception) throws SAXException {
log.warn(exception.getMessage());
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
log.error("Fatal error ", exception);
}
@Override
public void error(SAXParseException exception) throws SAXException {
log.error("Exception ", exception);
}
});
或者,不是记录错误,而是throw
它和catch
处理条目的位置,因此您可以打印条目本身以更好地指示错误。
答案 4 :(得分:0)
另一个原因是,您应该在mongodb设置中将IP地址(IPv4)列入白名单。希望它能解决!
答案 5 :(得分:0)
我通过将源Feed从http://www.news18.com/rss/politics.xml转换为https://www.news18.com/rss/politics.xml
解决了该问题使用http下面的代码创建了一个空文件,这导致了问题
String feedUrl = "https://www.news18.com/rss/politics.xml";
File feedXmlFile = null;
try {
feedXmlFile =new File("C://opinionpoll/newsFeed.xml");
FileUtils.copyURLToFile(new URL(feedUrl),feedXmlFile);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(feedXmlFile);
答案 6 :(得分:0)
一次使用inputstream,不要多次使用它,并且 做inputstream.close()