java - JAXB 编码 : Filter values of leaf elements

标签 java xml jaxb marshalling

我有一个相当复杂的 JAXB 树对象。 对于每个叶节点,我需要过滤其实际值

例如

<Book>
    <Title>Yogasana Vijnana: the Science of Yoga</Title>
    <Author>Dhirendra Brahmachari</Author>
    <Date>1966</Date>
</Book>

此处的叶节点为TitleauthorDate
想象一下,我需要为这个 JAXB 模型编写一个编码文档,每个叶节点的第一个字符都被删除:

<Book>
    <Title>ogasana Vijnana: the Science of Yoga</Title>
    <Author>hirendra Brahmachari</Author>
    <Date>966</Date>
</Book>


什么是最好的方法?
我看到了两个起点,但是,我目前卡住了。

<强>1。在 JAXB 模型中进行更改
是否有一些遍历机制可以用来获取任何 JAXB 对象(某种访问者模式或其他)的叶元素?

<强>2。钩入编码
也许我们可以加入编码,例如使用 XMLStreamWriter..

这种问题有没有优雅的解决方案?

最佳答案

另一种方法基于 XMLStreamWriter 类型的装饰器,它会简单地跳过文本内容的第一个字符,但您无法将其限制为叶子仅节点,它将对所有文本内容应用相同的逻辑,而不仅仅是叶节点,如果您的编码不像您的示例那样生成混合内容,这将不是问题。实际上,如果您没有混合内容(文本内容和节点混合在一起),则只有叶节点可以包含文本内容。

您的装饰器可能是这样的:

public class RemoveFirstCharacter implements XMLStreamWriter {

    private final XMLStreamWriter delegate;

    public RemoveFirstCharacter(final XMLStreamWriter delegate) {
        this.delegate = delegate;
    }

    @Override
    public void writeStartElement(final String localName) throws XMLStreamException {
        delegate.writeStartElement(localName);
    }

    @Override
    public void writeStartElement(final String namespaceURI, final String localName) 
        throws XMLStreamException {
        delegate.writeStartElement(namespaceURI, localName);
    }

    ...

    @Override
    public void writeCharacters(final String text) throws XMLStreamException {
        // Skip the first character
        delegate.writeCharacters(text.substring(1));
    }

    @Override
    public void writeCharacters(final char[] text, final int start, final int len)
        throws XMLStreamException {
        if (start == 0) {
            // Skip the first character
            delegate.writeCharacters(text, 1, len - 1);
        } else {
            delegate.writeCharacters(text, start, len);
        }
    }
}

那么你的代码将是:

// Create the marshaller for the class Book
JAXBContext jaxbContext = JAXBContext.newInstance(Book.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

// Create the main XMLStreamWriter
XMLOutputFactory output = XMLOutputFactory.newInstance();
XMLStreamWriter writer = output.createXMLStreamWriter(System.out);

// Apply the custom XMLStreamWriter that will remove the first character
// of each text content
jaxbMarshaller.marshal(book, new RemoveFirstCharacter(writer));

关于java - JAXB 编码 : Filter values of leaf elements,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42301081/

相关文章:

java - Spring Boot,Mockito,将模拟注入(inject)作用域 session bean

java - 使用 for 循环更改 JLabel 文本

java - tomcat多线程问题

c++ - QT读取XML文件,结构

java - 使用 JAXB 通过 SOAP 传递 HashMap<String,Object>

java - 使用 Java 8 CompletableFuture 同时从 java.lang.Process 读取 stdout/stderr?

java - 修改InputStream并将其转换为Outputstream

java - 带有 XSD JAVA 的 XML

xml - Jackson 或 JAXB,哪个更适合 JSON?

java - 解码时出现意外元素