【问题标题】:Using Multiple @XmlAnyElement in JAXB to manually handle </> Characters in Multiple Strings在 JAXB 中使用多个 @XmlAnyElement 手动处理多个字符串中的 </> 字符
【发布时间】:2018-10-18 16:48:10
【问题描述】:

我们正在使用 JAXB 来解组我们无法更改的预存储 XML。不幸的是,预存的 XML 包含一些 HTML 括号,&lt; and &gt;, 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 的解决方法?

【问题讨论】:

    标签: xml jaxb sax


    【解决方案1】:

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

    知道了这一点,您可以将 Article JAXB bean 重构为:

    @XmlRootElement
    public class Article {
    
      @XmlAnyElement(lax=true)
      protected List<Object> innerBeans;
    
    }
    

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 我们无法控制 XSD 或生成的 XML。我们唯一能做的就是读取最终的 XML 字符串。
      • 给定XSD中ArticleTitleAbstractText的内容模型是什么?如果没有混合,那么您如何期望 JAXB 知道那些元素可能具有混合内容?您是否考虑过为 JAXB 提供您自己的 XSD,这些 XSD 实际上反映了您所拥有的 XML 的实际情况?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-27
      • 1970-01-01
      • 1970-01-01
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 2013-11-17
      相关资源
      最近更新 更多