Использование Multiple @XmlAnyElement в JAXB для ручной обработкиСимволы в нескольких строках - PullRequest
0 голосов
/ 18 октября 2018

Мы используем JAXB для демонтажа предварительно сохраненного XML, который мы не можем изменить.К сожалению, предварительно сохраненный XML содержит несколько скобок HTML, < and >, without CDATA..Например, мы должны разобрать это с помощью JAXB (обратите внимание, что CDATA не существует):

<Article>
  <ArticleTitle>Note the unescaped inner HTML (T<sub>3</sub>) in the title</ArticleTitle>
  <Abstract>
     <AbstractText>This is another element that has unescaped HTML: T<sub>3</sub>. </AbstractText>
  </Abstract>
</Article>

Нам нужно сохранить данные HTML выше.JAXB подавляет их и дает нам неверные значения модели.

Одно из работающих решений - использовать @XmlAnyElement, а затем реализовать DomHandler (см. Ниже).

Но, к сожалению,только 1 @XmlAnyElement разрешен для каждого класса.Если я добавлю несколько, для Заголовка и Аннотация, только один из них будет работать одновременно. Так что это решение работает только для 1 поля, в котором есть эта проблема.Я пытался реализовать XmlAdapter (не DomHandler), но строка уже укорочена, поэтому я не могу использовать это решение, только вот это.

Заставить jaxb unmarshaller игнорироватьhtml Теги

@XmlAnyElement(value=AbstractTextHandler.class)
protected String abstractText=null;

затем реализуйте

public class AbstractTextHandler implements DomHandler<String, StreamResult> {
    private final Logger log = Logger.getLogger(getClass().getName());
    private static final String START_TAG = "<Abstract>";
    private static final String END_TAG = "</Abstract>";

    private StringWriter xmlWriter = new StringWriter(); 

    public StreamResult createUnmarshaller(ValidationEventHandler errorHandler) {
        return new StreamResult(xmlWriter);
    }

    public String getElement(StreamResult rt) {
        String xml = rt.getWriter().toString();
        int beginIndex = xml.indexOf(START_TAG) + START_TAG.length();
        int endIndex = xml.indexOf(END_TAG);
        String result = xml.substring(beginIndex, endIndex);
        log.info("Processing.." + result);
        return result;
    }

    public Source marshal(String n, ValidationEventHandler errorHandler) {
        try {
            String xml = START_TAG + n.trim() + END_TAG;
            StringReader xmlReader = new StringReader(xml);
            return new StreamSource(xmlReader);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Это должно работать для нескольких полей, но допускается только 1 @XmlAnyElement.

Есть лиспособ для нас использовать синтаксический анализатор SAX или что-то для обработки XML-кода, чтобы избежать удушья в этих скобках HTML?Или есть @XmlAnyElement обходной путь?

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Как указывает документ, @XmlAnyElement действует как механизм catch- (ALL) .По этой причине допускается только одно вхождение.

Зная это, вы можете изменить свой бин Article JAXB на:

@XmlRootElement
public class Article {

  @XmlAnyElement(lax=true)
  protected List<Object> innerBeans;

}

Таким образом, ArticleTitle и Abstract будут автоматически отменены.как JAXB-бины в список "innerBeans".

0 голосов
/ 18 октября 2018

Обработка смешанное содержимое через mixed="true" в объявлении xsd:complexType моделей содержимого ArticleTitle и AbstractText в XSD.

...