首页 > 解决方案 > 在java中解析xml时跳过元素的反序列化并将整个内容作为字符串获取

问题描述

我有一个如下的 XML:

<content>
  <p><b>Node:</b> Some information</p>
</content>

反序列化此 XML 时,我想将 p 标记内的内容作为字符串获取。

例如,如果我有一个如下的 java 类:

@Data
class Content {
  TextInParagraph p;
}

@Data
class TextInParagraph {
  String text;
}

我应该将文本的值设为“ <b>Node:</b> Some information”。

有没有一种方法可以使用 JAXB 或 Jackson XML 解析器完成以上操作?

我尝试在杰克逊上面反序列化,但我得到以下异常:

Expected END_ELEMENT, got event of type 1
java.io.IOException: Expected END_ELEMENT, got event of type 1

标签: javaxmljacksonjaxbjackson-dataformat-xml

解决方案


可悲的是,这是不可能的jackson-dataformat-xml

但是,使用 JAXB,您可以使用DomHandler

@XmlRootElement(name = "content")
@XmlAccessorType(XmlAccessType.FIELD)
public class Content {

    @XmlAnyElement(InnerXmlHandler.class)
    private String p;
}

处理程序

import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.StringReader;
import java.io.StringWriter;

public class InnerXmlHandler implements DomHandler<String, StreamResult> {

    private static final String START_TAG = "<p>";
    private static final String END_TAG = "</p>";

    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.lastIndexOf(END_TAG);
        return xml.substring(beginIndex, endIndex);
    }

    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);
        }
    }
}

这适用于您提供的示例,但甚至适用于嵌套<p>标签,例如:

<content>
  <p> This is some <ul><li>list</li></ul> and <p>nested paragraph</p></p>
</content>

但是,这仅在内部 HTML/XML 有效时才有效。以下将不起作用并引发异常,例如The element type "ul" must be terminated by the matching end-tag "</ul>".

<content>
  <p> This is some <ul>invalid xml </p>
</content>

这是因为 JAXB 的内部结构会遍历所有内部元素,尽管提供了 dom 处理程序。


推荐阅读