2017-09-01 24 views
0

我必须映射XML < - > Java对象,我使用JAXB进行编组和解组。这很棒。 现在我有一个问题:XML标签可以在不同的语言JAXB具有相同对象的动态注释

例(只有2种语言):

英文版:

<root> 
    <elementA/> 
    <elementB/> 
    <elementC/> 
</root> 

意大利语版本:

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

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

目标是有一个单一的对象,设置其语言,然后马歇尔和unmarshall容易。

接口或更多的对象并不是解决方案,因为每个语言涉及的对象都不容易作为例子,但是数百个对象经常互相嵌套。

+0

我从来没见过有人想要本地化XML元素名称。 – Rob

+0

您是否探索过将XSL转换应用于结果XML的可能方法? – yegodm

+0

XML定义应该用通用语言来定义。否则将问题分为两部分:1)转换为英文版本2)处理数据。 –

回答

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