MOXy Dynamix JAXB上下文解组为错误的属性名称

时间:2013-11-22 14:12:37

标签: java binding jaxb moxy

我目前正在尝试使用MOXy中的DynamicJaxbContext解组以下XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://somehost.com/schema_schedule_request.xsd">
    <header>
        <originator>MySatelliteCompany</originator>
        <recipient>Recipient</ recipient>
        <schedule_valid_from>2008-12-17T00:00:00Z</schedule_valid_from>
        <schedule_valid_to>2008-12-18T00:00:07Z</schedule_valid_to>
        <request_reference>HGT4285T3</request_reference>
        <generation_time>2008-12-16T08:24:00Z</generation_time>
     </header>
     <body>
         <schedule_request>
         <start_time>2008-12-17T09:30:47Z</start_time>
         <end_time>2008-12-17T09:33:47Z</end_time>
         <satellite_name>MySat</satellite_name>
         </schedule_request>
     </body>
</request>

它可以工作,但动态创建的Java类的属性与XML中给出的字段不对应。例如:<satellite_name>被解组为“satelliteName”。这使得为​​我的后端API编写自定义绑定文件非常困难,因为我必须首先解组我将获得的所有XML文件作为输入并手动写下相应的属性名称或编写另一个帮助我的帮助应用程序。 / p>

有没有办法改变这个MOXy行为,以便正确地解析字段名称,因为它们在XML中?

此外: 所以我在MOXy文档中找到了原因:

  

在元数据中找到的XML名称(复杂类型名称,元素名称,   属性名称)将被转换为Java标识符   “附录D:将XML名称绑定到Java”中描述的算法   “XML绑定的Java体系结构(JAXB)2.2的标识符”   规范(http://jcp.org/en/jsr/detail?id=222)。 - 更多信息请访问:   http://www.eclipse.org/eclipselink/documentation/2.4/moxy/dynamic_jaxb001.htm#BABCDJDF

但我的主要问题仍然存在:有没有办法关闭它或修改这种行为?

1 个答案:

答案 0 :(得分:0)

你的 ADDITION 是正确的,MOXy不会解组错误的属性名称,它只是解组对应于生成的类中映射的属性/字段名称的属性名称。

解决方案应该是什么

<强> binding.xml

JAXB中的默认XML Schema to Java命名规则是删除_。您可以提供绑定文件以使此行为不同。

<jaxb:bindings 
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">
    <jaxb:globalBindings underscoreBinding="asCharInWord"/>
</jaxb:bindings>

<强>演示

使用MOXy的动态JAXB,下面是如何利用绑定文件的示例。

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;

public class Demo {

    public static void main(String[] args) throws Exception {
        StreamSource schemaSource = new StreamSource("src/forum20146935/schema.xsd");
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(DynamicJAXBContextFactory.EXTERNAL_BINDINGS_KEY, new StreamSource("src/forum20146935/binding.xml"));
        JAXBContext jc = DynamicJAXBContextFactory.createContextFromXSD(schemaSource, null, Demo.class.getClassLoader(), properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum20146935/input.xml");
        DynamicEntity root = (DynamicEntity) unmarshaller.unmarshal(xml);
        System.out.println(root.get("foo_bar"));
    }

}

为什么不起作用?

正如我之前提到的,MOXy将基于XJC生成的相应映射字段/属性来建立动态属性名称。这恰好类似于属性名称具有_但相应的映射字段不具有的情况。

@XmlElement(name = "foo_bar", required = true)
protected String fooBar;

public String getFoo_Bar() {
    return fooBar;
}

public void setFoo_Bar(String value) {
    this.fooBar = value;
}

你可以做什么

  1. 使用已转换的密钥名称。
  2. 您可以使用MOXy getValueByXPath上的JAXBContext功能以更类似XML的方式与对象进行交互。

    import java.io.File;
    import java.util.*;
    
    import javax.xml.bind.*;
    import javax.xml.transform.stream.StreamSource;
    
    import org.eclipse.persistence.dynamic.DynamicEntity;
    import org.eclipse.persistence.jaxb.JAXBHelper;
    import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            StreamSource schemaSource = new StreamSource("src/forum20146935/schema.xsd");
            Map<String, Object> properties = new HashMap<String, Object>(1);
            properties.put(DynamicJAXBContextFactory.EXTERNAL_BINDINGS_KEY, new StreamSource("src/forum20146935/binding.xml"));
            JAXBContext jc = DynamicJAXBContextFactory.createContextFromXSD(schemaSource, null, Demo.class.getClassLoader(), properties);
    
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            File xml = new File("src/forum20146935/input.xml");
            DynamicEntity root = (DynamicEntity) unmarshaller.unmarshal(xml);
    
            String fooBar = JAXBHelper.getJAXBContext(jc).getValueByXPath(root, "foo_bar/text()", null, String.class);
            System.out.println(fooBar);
        }
    
    }