使用JAXB来解组一个XML字符串,但得到空单

问题描述:

问题解决使用JAXB来解组一个XML字符串,但得到空单

更改后的XmlElementRef将注释@XmlElementRef(NAME = “选项”,类型= Option.class,需要= FALSE),并添加@XmlRootElement( NAME = “选项”),以Option.class


更新:

我已经添加了两个类(选项和可选项)为劳瑞懒懒的建议和修改GuiMOProperties类,如下

@XmlAccessorType(XmlAccessType.FIELD) 
public class GuiMOProperties 
{ 
    @XmlElement(name="Grouping") 
    private boolean     grouping; 
    @XmlElement(name="Type") 
    private String     type; 
    @XmlElement(name="Regex") 
    private String     regex; 
    @XmlElement(name="DisplayName") 
    private String     displayName; 
    @XmlElement(name="Options") 
    private Options     options; 
    @XmlElement(name="Mask") 
    private String     mask; 
    @XmlElement(name="DefaultValue") 
    private String     defaultValue; 
} 

但有一些例外,当我有新的JAXBContext的实例如下:

JAXBContext jaxbContext = JAXBContext.newInstance(GuiMOProperties.class); 


java.lang.IllegalArgumentException: can't parse argument number: ''{0}'' 
at java.text.MessageFormat.makeFormat(MessageFormat.java:1429) 
at java.text.MessageFormat.applyPattern(MessageFormat.java:479) 
at java.text.MessageFormat.<init>(MessageFormat.java:362) 
at java.text.MessageFormat.format(MessageFormat.java:840) 
at com.sun.xml.internal.bind.v2.model.impl.Messages.format(Messages.java:117) 
at com.sun.xml.internal.bind.v2.model.impl.ReferencePropertyInfoImpl.calcTypes(ReferencePropertyInfoImpl.java:171) 
at com.sun.xml.internal.bind.v2.model.impl.ReferencePropertyInfoImpl.link(ReferencePropertyInfoImpl.java:372) 
at com.sun.xml.internal.bind.v2.model.impl.ClassInfoImpl.link(ClassInfoImpl.java:1257) 
at com.sun.xml.internal.bind.v2.model.impl.RuntimeClassInfoImpl.link(RuntimeClassInfoImpl.java:182) 
at com.sun.xml.internal.bind.v2.model.impl.ModelBuilder.link(ModelBuilder.java:439) 
at com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder.link(RuntimeModelBuilder.java:118) 
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:443) 
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277) 
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124) 
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123) 
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247) 
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234) 
at javax.xml.bind.ContextFinder.find(ContextFinder.java:462) 
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641) 
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584) 
at devicemanage.utility.Tree2xml.omElementToGuiMOPropertiesList(Tree2xml.java:332) 
at devicemanage.service.appdeploy.DeviceMgtServiceImpl.getMOProperties(DeviceMgtServiceImpl.java:250) 
at devicemanage.service.appdeploy.DeviceMgtServiceImpl.access$0(DeviceMgtServiceImpl.java:238) 
at devicemanage.service.appdeploy.DeviceMgtServiceImpl$1.load(DeviceMgtServiceImpl.java:233) 
at devicemanage.service.appdeploy.DeviceMgtServiceImpl$1.load(DeviceMgtServiceImpl.java:1) 
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3527) 
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2319) 
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2282) 
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2197) 
at com.google.common.cache.LocalCache.get(LocalCache.java:3937) 
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941) 
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824) 
at devicemanage.service.appdeploy.DeviceMgtServiceImpl.findMOPropertiesByDeviceType(DeviceMgtServiceImpl.java:208) 
at devicemanage.service.appdeploy.DeviceMgtServiceImpl$$FastClassBySpringCGLIB$$1a89f063.invoke(<generated>) 
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) 
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266) 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) 
at devicemanage.service.appdeploy.DeviceMgtServiceImpl$$EnhancerBySpringCGLIB$$97274215.findMOPropertiesByDeviceType(<generated>) 
at TestDeviceMgtService.testFindMOPropertiesByDeviceType(TestDeviceMgtService.java:38) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:72) 
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:81) 
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:216) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:82) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:60) 
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:67) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:162) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 
Caused by: java.lang.NumberFormatException: For input string: "''{0}''" 
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) 
    at java.lang.Integer.parseInt(Integer.java:569) 
    at java.lang.Integer.parseInt(Integer.java:615) 
    at java.text.MessageFormat.makeFormat(MessageFormat.java:1427) 
    ... 78 more 

我有一个类定义为下面的JAXB解析:

@XmlAccessorType(XmlAccessType.FIELD) 
public class GuiMOProperties 
{ 
    @XmlElement(name="Grouping") 
    private boolean     grouping; 
    @XmlElement(name="Type") 
    private String     type; 
    @XmlElement(name="Regex") 
    private String     regex; 
    @XmlElement(name="DisplayName") 
    private String     displayName; 
    @XmlElement(name="Options") 
    @XmlJavaTypeAdapter(OptionsAdapter.class) 
    private GuiMOOption     options; 
    @XmlElement(name="Mask") 
    private String     mask; 
    @XmlElement(name="DefaultValue") 
    private String     defaultValue; 
} 

而且我必须解析如下的xml字符串:

  <VolumeUpKey> 
       <Type/> 
       <Regex/> 
       <DisplayName/> 
       <Options>testOptions</Options> 
       <Mask/> 
       <DefaultValue/> 
      </VolumeUpKey> 
      <SSID> 
       <Type/> 
       <Regex/> 
       <DisplayName/> 
       <Options> 
        <Option name="1" value="1"></Option> 
        <Option name="2" value="2"></Option> 
        <Option name="3" value="3"></Option> 
        <Option name="4" value="4"></Option> 
       </Options> 
       <Mask/> 
       <DefaultValue/> 
      </SSID> 

在OptionsAdapter.class的unmarshal方法中,第一个Options元素工作正常,有一个字符串“testOptions”输入。然而,第二个选项元素没有。输入的参数将会出现,但不是字符串<Option name="1" value="1"></Option><Option name="2" value="2"></Option><Option name="3" value="3"></Option><Option name="4" value="4"></Option>

的OptionsAdapter.class如下

public class OptionsAdapter extends XmlAdapter<String, GuiMOOption> 
{ 
    @Override 
    public GuiMOOption unmarshal(String v) throws Exception 
    { 
     try 
     { 
      System.out.println("unmarshal string : " + v); 
     } catch (Exception e) 
     { 
      // TODO: handle exception 
     } 

     return null; 
    } 

    @Override 
    public String marshal(GuiMOOption v) throws Exception 
    { 
     // TODO Auto-generated method stub 
     return null; 
    } 
} 

任何帮助理解。

虽然JAXB可以在没有适配器的情况下处理它,但混合内容并不十分简单。

可以定义的选项字段的类型选项(而不是GuiMOOption):

 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "Options", propOrder = { 
    "content" 
}) 
public class Options { 

    @XmlElementRef(name = "field", type = JAXBElement.class, required = false) 
    @XmlMixed 
    protected List content; 

    public List getContent() { 
     if (content == null) { 
      content = new ArrayList(); 
     } 
     return this.content; 
    } 
} 

列表将包含JAXBElement<Option>类型和字符串的元素,其中的选择是一个类

 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Option { 
    @XmlAttribute 
    protected String name; 
    @XmlAttribute 
    protected String value; 
    //... 
} 

您必须迭代列表以了解您是否具有第一个或第二个XML表单。在第一种情况下,只会有一个字符串。在第二种情况下,在包装的选项对象中可能会有空白字符串。

+0

嗨,谢谢你的回答。你的意思是我必须添加两个类Options和Option,然后删除@XmlJavaTypeAdapter注释。让GuiMOProperties的选项字段变成XMLElement(name =“Options”)? – Bruce

+0

这就是主意。 - 我用了新的名字,不知道你的GuiMOOption类型是如何定义的。 – laune

+0

我还没有定义GuiMOOption,但添加了Options和Option后,我的更新后的帖子出现了一些异常。谢谢 – Bruce