Получение исключения при оценке выражения XPath в Java
Я пытаюсь научиться использовать выражения Xpath с Java. Я использую Jtidy для преобразования HTML-страницы в XHTML, чтобы я мог легко разобрать ее с помощью выражений XPath. У меня есть следующий код:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = ConvertXHTML("https://twitter.com/?lang=fr");
//Create XPath
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath Inst= xpathfactory.newXPath();
NodeList nodes = (NodeList)Inst.evaluate("//p/@align",doc,XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); ++i)
{
Element e = (Element) nodes.item(i);
System.out.println(e);
}
public Document ConvertXHTML(String link){
try{
URL u = new URL(link);
BufferedInputStream instream=new BufferedInputStream(u.openStream());
FileOutputStream outstream=new FileOutputStream("out.xhtml");
Tidy c=new Tidy();
c.setShowWarnings(false);
c.setInputEncoding("UTF-8");
c.setOutputEncoding("UTF-8");
c.setXHTML(true);
return c.parseDOM(instream,outstream);
}
Это нормально работает для большинства URL, но этот:
Я получаю это исключение из-за этого:
javax.xml.transform.TransformerException: индекс -1 выходит за границы.....
Ниже приведена часть трассировки стека, которую я получаю:
javax.xml.transform.TransformerException: Index -1 out of bounds for length 128
at java.xml/com.sun.org.apache.xpath.internal.XPath.execute(XPath.java:366)
at java.xml/com.sun.org.apache.xpath.internal.XPath.execute(XPath.java:303)
at java.xml/com.sun.org.apache.xpath.internal.jaxp.XPathImplUtil.eval(XPathImplUtil.java:101)
at java.xml/com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.eval(XPathExpressionImpl.java:80)
at java.xml/com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:89)
at files.ExampleCode.GetThoselinks(ExampleCode.java:50)
at files.ExampleCode.DoSomething(ExampleCode.java:113)
at files.ExampleCode.GetThoselinks(ExampleCode.java:81)
at files.ExampleCode.DoSomething(ExampleCode.java:113)
Я не уверен, что проблема в преобразованном xhtml веб-сайте или что-то еще. Может кто-нибудь сказать, что не так в коде? Любые изменения будут полезны.
2 ответа
Как правило, я бы сказал, что исключение индекса границ, происходящее из глубины движка XPath, является ошибкой в движке XPath. Единственное предостережение - если что-то структурно не так с DOM, который ищет движок XPath; процессор XPath имеет право делать разумные предположения о том, что DOM действителен, и аварийно завершать работу, если это не так. В этом случае это будет ошибка в Tidy, которая создала DOM.
У меня была аналогичная проблема с использованием оценки xpath в документе, созданном JTidy. Я обошел это, заставив JTidy сериализовать созданную им модель DOM в файл, а затем проанализировать этот xml-файл с помощью javax.xml.parsers.DocumentBuilder, чтобы получить вторую версию DOM. Как ни странно, использование второго позволяет избежать исключения за пределами границ и сработало. Используйте следующий код:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
// If you don't do the following, it will take a full minute to parse the xml document (presumably the time-out
// period for trying to load the DTD). See https://stackoverflow.com/questions/6204827/xml-parsing-too-slow.
documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = tidy.parseDOM(input, null);
FileOutputStream fos = new FileOutputStream("temp.xml");
tidy.pprint(doc, fos);
fos.close();
doc = documentBuilder.parse("temp.xml");