简体   繁体   English

使用JAXB解组xml字符串但得到一个空字符串

[英]Using JAXB to unmarshal a xml string but get empty one

Problem solved 问题解决了

After change the XmlElementRef annotation to @XmlElementRef(name = "Option", type = Option.class, required = false) and add @XmlRootElement(name = "Option") to Option.class 将XmlElementRef批注更改为@XmlElementRef(name =“ Option”,类型= Option.class,required = false)并将@XmlRootElement(name =“ Option”)添加到Option.class


Update: 更新:

I have added two classes(Options and Option) as laune's recommend and modified the GuiMOProperties class as below 我添加了两个类(Options和Option)作为laune的推荐,并修改了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;
}

But got some exception when I have to new an instance of JAXBContext as below: 但是当我必须如下创建新的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

I have a class defined as below for JAXB parsing: 我有一个为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;
}

And the xml string I have to parsed as below: 以及我必须解析的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>

In the unmarshal method of my OptionsAdapter.class, the first one Options element works fine, there has a string "testOptions" input. 在我的OptionsAdapter.class的unmarshal方法中,第一个Options元素可以正常工作,其中有一个字符串“ testOptions”输入。 However, the second one Options element didn't. 但是,第二个Options元素则没有。 The input paramater will be come \\n\\t\\t\\t\\t, but not a string <Option name="1" value="1"></Option><Option name="2" value="2"></Option><Option name="3" value="3"></Option><Option name="4" value="4"></Option> . 输入的参数为\\ n \\ t \\ t \\ t \\ t,但不是字符串<Option name="1" value="1"></Option><Option name="2" value="2"></Option><Option name="3" value="3"></Option><Option name="4" value="4"></Option>

The OptionsAdapter.class as below 如下所示的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;
    }
}

Any help is appreciated. 任何帮助表示赞赏。

Mixed content isn't quite straightforward, although JAXB can handle it without an adapter. 混合内容并不是很简单,尽管JAXB可以在没有适配器的情况下进行处理。

You can define the type of the options field as Options (instead of GuiMOOption): 您可以将选项字段的类型定义为选项(而不是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;
    }
}

The List will contain elements of type JAXBElement<Option> and String, where Option is a class 该列表将包含JAXBElement<Option>和String类型的元素,其中Option是一个类

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

You have to iterate the List to learn whether you have the first or the second XML form. 您必须遍历List以了解您是第一种还是第二种XML形式。 In the first case there'll be just one String. 在第一种情况下,只会有一个String。 In the second case, there may be white space strings among the wrapped Option objects. 在第二种情况下,包装的Option对象之间可能会有空白字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM