У меня есть некоторый код Java, который определяет пространство имен элемента корневого уровня документа xml с использованием SAX. Если пространство имен «http://sbgn.org/libsbgn/pd/0.1», оно должно вернуть версию 1. Если пространство имен «http://sbgn.org/libsbgn/0.2», версия должна быть 2. Таким образом, весь код читает первый элемент и устанавливает переменную на основе пространства имен. Вот код:
private static class VersionHandler extends DefaultHandler
{
private int version = -1;
@Override
public void startElement (String uri, String localName, String qName, Attributes attributes) throws SAXException
{
if ("sbgn".equals (qName))
{
System.out.println (uri);
if ("http://sbgn.org/libsbgn/0.2".equals(uri))
{
version = 2;
}
else if ("http://sbgn.org/libsbgn/pd/0.1".equals(uri))
{
version = 1;
}
else
{
version = -1;
}
}
}
public int getVersion() { return version; }
};
public static int getVersion(File file) throws SAXException, FileNotFoundException, IOException
{
XMLReader xr;
xr = XMLReaderFactory.createXMLReader();
VersionHandler versionHandler = new VersionHandler();
xr.setContentHandler(versionHandler);
xr.setErrorHandler(versionHandler);
xr.parse(new InputSource(
InputStreamToReader.inputStreamToReader(
new FileInputStream (file))));
return versionHandler.getVersion();
}
Это работает, но есть две проблемы:
- Это неэффективно, потому что будет проанализирован весь документ, даже если нужен только первый элемент.
- Что еще более важно, этот код иногда (очевидно, в зависимости от конфигурации брандмауэра) вызывает UnknownHostException следующим образом:
java.net.UnknownHostException: www.w3.org at java.net.PlainSocketImpl.connect(Unknown Source) at java.net.SocksSocketImpl.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at sun.net.NetworkClient.doConnect(Unknown Source) at sun.net.www.http.HttpClient.openServer(Unknown Source) at sun.net.www.http.HttpClient.openServer(Unknown Source) at sun.net.www.http.HttpClient.(Unknown Source) at sun.net.www.http.HttpClient.New(Unknown Source) at sun.net.www.http.HttpClient.New(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startDTDEntity(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.setInputSource(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(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.AbstractSAXParser.parse(Unknown Source) at org.sbgn.SbgnVersionFinder.getVersion(SbgnVersionFinder.java:57)
Итак, мои вопросы:
- По-видимому, этот фрагмент кода подключается к Интернету. Как я могу этого избежать? Помимо того, что это приводит к проблемам с брандмауэрами, он также излишне медленный.
- Почему он подключается к Интернету? Пожалуйста, помогите мне понять логику здесь, в этом не должно быть абсолютно никакой необходимости.
- Есть ли более эффективный способ определить пространство имен корневого элемента XML-документа?
Изменить: вот ссылка на образец документа, который я пытаюсь разобрать следующим образом: https://libsbgn.svn.sourceforge.net/svnroot/libsbgn/trunk/test-files/PD/adh.sbgn
Edit2: примечание относительно решения этой ошибки: на самом деле проблема была вызвана тем, что анализировался неправильный документ, вместо предполагаемого документа я анализировал документ XHMTML, который на самом деле ссылается на www.w3.org. Конечно, решение состоит в том, чтобы использовать правильный документ. Тем не менее, я счел полезным добавить эту строку:
xr.setEntityResolver(null);
Чтобы предотвратить переход xerces через Интернет, когда это действительно совершенно не нужно.