具有相同对象的JAXB动态注释

时间:2017-09-01 14:52:22

标签: java xml jaxb annotations

我必须映射XML< - > Java对象,我使用JAXB进行编组和解组。这很棒。 现在我遇到了一个问题:xml标签可以使用不同的语言

示例(只有2种语言):

英文版:

<radice>
   <elementoA/>
   <elementoB/>
   <elementoC/>
</radice>

意大利语版本:

{{1}}

问题是:如何使用一个java对象管理更多语言,以及更多具有相同结构但不同元素名称的xml源? 有没有办法动态更改注释?

目标是拥有一个单一的对象,设置其语言,然后轻松地编组和取消编组。

接口或更多对象不是解决方案,因为每个语言所涉及的对象并不容易,但数百个通常彼此嵌套。

1 个答案:

答案 0 :(得分:0)

以下是如何使用自定义XMLStreamWriter完成的草案。在这些示例中,需要两个Maven依赖项(使用Java 7;使用Java 8,代码可以更简单):

    <dependency>
        <groupId>net.java.dev.stax-utils</groupId>
        <artifactId>stax-utils</artifactId>
        <version>20070216</version>
    </dependency>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>19.0</version>
    </dependency>

以下是完成工作的片段:

@XmlRootElement(name = ROOT)
public static class Root {
    static final String ROOT = "root";
    static final String ELEMENT_A = "elementA";

    @XmlElement(name = ELEMENT_A)
    public Element element_a;
    public static class Element {}
}

public static void main(String[] args) throws Exception {
    final Root root = new Root();
    root.element_a = new Root.Element();

    final JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
    final Marshaller marshaller = jaxbContext.createMarshaller();

    final XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
    final XMLStreamWriter writer = outputFactory.createXMLStreamWriter(System.out);
    final LocalizingXmlStreamWriter localizingWriter = new LocalizingXmlStreamWriter(writer, Locale.ENGLISH);
    marshaller.marshal(root, localizingWriter);
}

static class LocalizingXmlStreamWriter extends javanet.staxutils.IndentingXMLStreamWriter {
    final static Map<String, ImmutableMap<String, String>> localizations = Maps.toMap(
        Arrays.asList(Locale.ENGLISH.getLanguage(), Locale.ITALIAN.getLanguage()),
        new Function<String, ImmutableMap<String, String>>() {
            @Override
            public ImmutableMap<String, String> apply(String lang) {
                if (Locale.ENGLISH.getLanguage().equals(lang)) {
                    return Maps.toMap(Arrays.asList(ROOT, ELEMENT_A),
                        Functions.<String>identity());
                }
                else if (Locale.ITALIAN.getLanguage().equals(lang)) {
                    return Maps.toMap(Arrays.asList(ROOT, ELEMENT_A),
                        new Function<String, String>() {
                            @Override
                            public String apply(String tag) {
                                switch (tag) {
                                    case ROOT:
                                        return "radice";
                                    case ELEMENT_A:
                                        return "elementoA";
                                    default:
                                        return tag;
                                }
                            }
                        });
                }
                else throw new IllegalStateException();
            }
        }
    );

    private final ImmutableMap<String, String> localization;

    public LocalizingXmlStreamWriter(XMLStreamWriter writer, Locale locale) {
        super(writer);
        final String language = locale.getLanguage();
        localization = localizations.get(language);
        Preconditions.checkArgument(localization != null, 
            "not supported language %s", language);
    }

    @Override
    public void writeStartElement(String prefix, String localName, String namespaceURI) 
        throws XMLStreamException 
    {
        final String localizedTag = localization.get(localName);
        super.writeStartElement(prefix, localizedTag, namespaceURI);
    }
}