Jackson XML «Необъявленная общая сущность», вызванная пользовательской сущностью

#jackson-dataformat-xml

#jackson-dataformat-xml

Вопрос:

Я десериализирую большой XML-файл (не мой), и он содержит пользовательские сущности, определенные как:

 <!ENTITY math "mathematics">
  

и элементы, используемые таким образом:

 <field>amp;math;</field>
  

Когда я пытаюсь десериализовать его с помощью:

 XmlMapper xmlMapper = new XmlMapper();
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
return xmlMapper.readValue(classloader.getResourceAsStream("file.xml"), MyClass.class);
  

Я получаю эту ошибку:
com.fasterxml.jackson.databind.Исключение JsonMappingException: необъявленная общая сущность «математика»

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

  1. Есть ли способ пометить эти пользовательские сущности как действительные? Например, создать для них перечисление или что-то в этом роде?
  2. Если нет, есть ли флаг, чтобы просто анализировать их как строки?

Обновление: я смог обойти эту проблему, в основном выполнив поиск-замену в текстовом файле. Это довольно уродливое решение, и если у кого-то есть идея получше, я весь внимание. 🙂

Ответ №1:

Я знаю, что это может быть немного поздно, но на всякий случай, если кто-то еще застрял в той же проблеме:

Вы должны установить пользовательский XmlResolver в качестве свойства XMLPUTFACTORY:

 import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.ctc.wstx.api.WstxInputProperties;
import javax.xml.stream.XMLResolver;
import javax.xml.stream.XMLStreamException;

var xmlMapper = new XmlMapper();
xmlMapper.getFactory().getXMLInputFactory().setProperty(
    WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER,
    new XMLResolver() {
        @Override
        public Object resolveEntity(String publicId, String systemId, String baseUri, String ns) throws XMLStreamException {
            // replace the entity with a string of your choice, e.g.
            switch (ns) {
                case "nbsp": 
                    return " ";
                default: 
                    return "";
            }
            // some useful tool is org.apache.commons.text.StringEscapeUtils
            // e.g.
            // return StringEscapeUtils.escapeXml10(StringEscapeUtils.unescapeHtml4('amp;'   ns   ';'));
        }
    }
);

// then xmlMapper.readValue....