在JAXB中使用多个@XmlAnyElement手动处理多个字符串中的<!---->字符

时间:2018-10-18 16:48:11

标签: xml jaxb sax

我们正在使用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),但是字符串已经被截断了,所以我不能只使用这个解决方案。

Force jaxb unmarshaller to ignore html Tags

@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 :(得分:1)

正如文档所指出的,@XmlAnyElement充当catch- (ALL)机制。这就是为什么只允许出现一次的原因。

了解到,您可以将Article JAXB bean重构为:

@XmlRootElement
public class Article {

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

}

这样,ArticleTitle和Abstract将作为JAXB bean自动解组到“ innerBeans”列表中。

答案 1 :(得分:0)

通过XSD中mixed="true"xsd:complexType内容模型的ArticleTitle声明中的AbstractText处理混合内容