【问题标题】:Use object with toXML method inside a JAXB-annotated object?在带有 JAXB 注释的对象中使用带有 toXML 方法的对象?
【发布时间】:2014-04-02 15:41:43
【问题描述】:

我是一名网络服务开发人员。在我的雇主那里,他们有一个非常丰富的数据模型,我可能无法更改太多。

几乎所有对象都能够通过 toXML() 方法将自己呈现为 XML。将它们视为哈希映射,我们直到运行时才知道完整的字段集。

我正在尽可能地利用 JAXB,因此我的一些 Web 服务对象是常规 POJO,如您所期望的那样进行了注释。但是,我想在带有 JAXB 注释的 POJO 中添加一个旧对象,并调用它的 toXML()。

例如:

@XmlRootElement
class Metadata {
    @XmlAttribute String serviceVersion;
    @XmlAttribute String applicationVersion;
    @XmlElement User user; // this is our object with it's own toXML method
}

理想情况下,我希望看到编组后的结果为:

<metadata serviceVersion="5.1" applicationVersion="12.1">
    <user id="bmauter" firstname="Brian"/>
</metadata>

我研究过扩展 XmlAdapter,但输出类似于:

<metadata serviceVersion="5.1" applicationVersion="12.1">
    <user>&lt;user id=&quot;bmauter&quot; firstname=&quot;Brian&quot;/&gt;</user>
</metadata>

然后我想我在某个地方读到了让 XmlAdapter 将我的对象转换为 org.w3c.dom.Element。我决定尝试一下,但是因为“JAXB 无法处理接口”而失败了。

如何将这样的对象嵌入到带有 JAXB 注释的常规 POJO 中?

谢谢!

更新:这是我正在尝试修复的实际示例。 (再次更新以表明该组字段名称直到运行时才知道。)

import java.util.HashMap;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
public class Metadata {
    @XmlAttribute String serviceVersion = "5.1";
    @XmlAttribute String applicationVersion = "12.1";
    @XmlElement @XmlJavaTypeAdapter(UserXmlAdapter.class) User user = new User();

    static class User extends Row {
        public User() {
            tablename = "users";
            fields.put( "id", "bmauter" );
            fields.put( "firstname", "Brian" );
        }
    }

    static class Row {
        String tablename = null;
        HashMap<String, Object> fields = new HashMap<String, Object>();

        public String toXML() {
            StringBuilder result = new StringBuilder();
            result.append( "<" ).append( tablename );
            for( String fieldName : fields.keySet() ) {
                result.append( " " ).append( fieldName ).append( "=\"" ).append( fields.get( fieldName ) ).append( "\"" );
            }
            result.append( "/>" ); 
            return result.toString();
        }
    }

    static class UserXmlAdapter extends XmlAdapter<String, User> {
        @Override public User unmarshal( String v ) throws Exception { return null; }
        @Override public String marshal( User user ) throws Exception { return user.toXML(); }
    }

    public static void main( final String[] args ) throws Exception {
        JAXBContext context = JAXBContext.newInstance( Metadata.class );
        context.createMarshaller().marshal( new Metadata(), System.out );
    }
}

【问题讨论】:

  • 您是否尝试过将用户声明为@XmlValue String user;?您可以将用户存储为非 jaxb 字段并在 getUser() 方法中返回其 XML。
  • 对于给定的父元素,只能有其中一个 @XmlValue 注释。即便如此,它仍然会转义文本。 99.999% 的时间它会做你想做的事。我有点惊讶我们无法将外部生成的 XML 粘贴到 jaxb 对象的中间。

标签: java xml jaxb pojo


【解决方案1】:

当你有以下情况时

@XmlRootElement
class Metadata {
    @XmlAttribute String serviceVersion;
    @XmlAttribute String applicationVersion;
    @XmlElement User user; // this is our object with it's own toXML method
}

User 对象将根据其映射在 Metadata 对象的 XML 中呈现。你不需要做任何特别的事情。

【讨论】:

  • 谢谢,但我希望 toXML 的结果出现在 JAXB 输出中。顺便说一句,我很谦虚你的回答。
  • @bmauter - 我不推荐这种方法。如果您的toXML 方法只返回一个String,则它不能与XMLStreamWriterNode 等其他元帅输出很好地配合使用。如果toXML 方法基于您的JAXB 映射无论如何都要得到相同的结果。
  • 不幸的是,直到运行时我才知道完整的字段集。没有什么可注释的。还有其他适合我的东西吗?如果它返回 JAXBElement 怎么办?我将如何以编程方式构建它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
相关资源
最近更新 更多