Существует ли Java XML API, который может анализировать документ без разрешения символьных объектов?

У меня есть программа, которая должна анализировать XML, содержащий символьные объекты. Самой программе не нужно их разрешать, а их список велик и будет меняться, поэтому я хочу по возможности избегать явной поддержки этих сущностей.

Вот простой пример:

<?xml version="1.0" encoding="UTF-8"?>
<xml>Hello there &something;</xml>

Существует ли Java XML API, который может успешно анализировать документ без разрешения (нестандартных) символьных объектов? В идеале это должно было бы преобразовать их в специальное событие или объект, с которым можно было бы обращаться особым образом, но я бы согласился на вариант, который молча подавлял бы их.

Ответ и пример:

Скаффман дал мне ответ: используйте парсер StAX с IS_REPLACING_ENTITY_REFERENCES, установленным в false.

Вот код, который я набросал, чтобы попробовать:

XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
XMLEventReader reader = inputFactory.createXMLEventReader(
    new FileInputStream("your file here"));

while (reader.hasNext()) {
    XMLEvent event = reader.nextEvent();
    if (event.isEntityReference()) {
        EntityReference ref = (EntityReference) event;
        System.out.println("Entity Reference: " + ref.getName());
    }
}

Для приведенного выше XML будет напечатано «Entity Reference: something».


person Kaypro II    schedule 22.11.2009    source источник
comment
Вы можете привести пример XML-файла?   -  person TofuBeer    schedule 22.11.2009
comment
Если у вас есть сущности, они должны быть определены, иначе ваш документ недействителен.   -  person Thorbjørn Ravn Andersen    schedule 22.11.2009


Ответы (4)


API STaX поддерживает понятие не заменять ссылки на символьные сущности посредством IS_REPLACING_ENTITY_REFERENCES:

Требует, чтобы синтаксический анализатор заменял ссылки на внутренние сущности их заменяющим текстом и сообщал о них как о символах.

Его можно установить в XmlInputFactory, который затем, в свою очередь, используется для построения XmlEventReader или XmlStreamReader. Тем не менее, API осторожно заявляет, что это свойство предназначено только для того, чтобы заставлять реализацию выполнять замену, а не заставлять ее не заменять их. Тем не менее, это стоит попробовать.

person skaffman    schedule 22.11.2009
comment
Это ИМЕННО то, что я хочу. Если вы установите для этого свойства значение false, вы увидите события EntityReference в потоке, из которых вы можете получить имя объекта с помощью метода getName(). - person Kaypro II; 22.11.2009

Анализ SAX с помощью org.xml.sax .EntityResolver может подойти для ваших целей. Вы наверняка могли бы подавить их, и вы, вероятно, могли бы найти способ оставить их нерешенными.

Это учебник кажется наиболее подходящим: он показывает, как преобразовать объекты в строки.

person Jim Ferrans    schedule 22.11.2009
comment
Я попробовал это. Похоже, что EntityResolvers используются только для внешних сущностей: в этом случае метод resolveEntity(...) не вызывается, а синтаксический анализатор завершается с ошибкой org.xml.sax.SAXParseException: на сущность что-то ссылались, но не объявлено. - person Kaypro II; 22.11.2009

Я не разработчик Java, но я «думаю», что классы Java xml поддерживают функциональность, аналогичную .net, для достижения этой цели. В .net классе xmlreadersettings вы устанавливаете для свойства ProhibitDtd значение false и устанавливаете для свойства XmlResolver значение null. Это приведет к тому, что синтаксический анализатор будет игнорировать объекты, на которые ссылаются извне, не создавая исключения при их чтении. Я только что выполнил поиск в Google по запросу «Java ignore enity» и получил множество результатов, некоторые из которых касаются этой темы. Я понимаю, что это не полный ответ на ваш вопрос, но он должен указать вам полезное направление.

person bill seacham    schedule 22.11.2009

У меня работает только при отключении поддержки внешних сущностей:

XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
person user2050348    schedule 07.02.2013