简体   繁体   中英

How can I unmarshal an XML document with an attribute that allows multiple enumeration values in jibx?

I want to use Jibx to unmarshal the following XML (stored in a file called test.xml):

<?xml version="1.0" encoding="UTF-8"?>
<rootElement attrWithEnum="avalue anothervalue" xsi:schemaLocation="my:target:ns simple.xsd" xmlns="my:target:ns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</rootElement>

I defined the schema (in a file called simple.xsd) like so:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="my:target:ns" xmlns="my:target:ns" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">            
    <xs:element name="rootElement">
        <xs:complexType>
            <xs:attribute name="attrWithEnum" use="required">
                <xs:simpleType>
                    <xs:list>
                        <xs:simpleType>
                            <xs:restriction base="xs:string">
                                <xs:enumeration value="avalue"/>
                                <xs:enumeration value="anothervalue"/>
                            </xs:restriction>
                        </xs:simpleType>
                    </xs:list>
                </xs:simpleType>
            </xs:attribute>
        </xs:complexType>
    </xs:element>    
</xs:schema>

generated Java files from it using the org.jibx.schema.codegen.CodeGen tool and wrote this test program:

package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import org.jibx.runtime.BindingDirectory;
import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;

import my.target.ns.RootElement;

public final class Program {

    public static void main(final String[] args) {                

        try {

            IBindingFactory bfact = BindingDirectory.getFactory(RootElement.class);
            IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
            FileInputStream in = new FileInputStream(new File("test.xml"));

            RootElement data = (RootElement) uctx.unmarshalDocument(in, null);

            // This is not what I was expecting. I was expecting 
            // List<RootElement.Enumeration> (or equivalent) not
            // a single RootElement.Enumeration instance
            RootElement.Enumeration attrValue = data.getAttrWithEnum();

            System.out.println(attrValue);

        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }
}

This program fails with the error:

org.jibx.runtime.JiBXException: No match found for value 'avalue anothervalue' in enum class my.target.ns.RootElement$Enumeration

If I tweak my input XML like so (ie only set a single enum value) it works (prints AVALUE ).

<rootElement attrWithEnum="avalue" xsi:schemaLocation="my:target:ns simple.xsd" xmlns="my:target:ns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

So, it seems that jibx does not like that I want to allow a list of enumeration values (I was expecting getAttrWithEnum to return a collection but it returns a single object - see the comment in the code example above).

The same XSD works fine when I use jaxb (generating the java files using xjc ), so I think my XSD is valid (though if there is a better way to define what I want, that would be fine).

My question therefore is:

How can I unmarshal an XML document with an attribute that allows multiple enumeration values in jibx?

I generated a RootElement class with xjc from your schema. The field for the attrWithEnum attribute became List<String> attrWithEnum which would divide each word in the attribute as a separate string in the list. This would allow any string value, not only those defined in the enumeration.

Changing it to only String attrWithEnum would of course store the attribute as is.

I changed the type to an enum:

enum AttrEnum {
    avalue,
    anothervalue
}
@XmlAttribute(name = "attrWithEnum", required = true)
public List<AttrEnum> attrWithEnum;

Using JAXB (I've never used Jibx) this gives me a list of only valid values. Any value in the attribute that is not defined in the enumeration is returned as a null value.

Changing the field to AttrEnum attrWithEnum would only return a non-null value if the attribute only contains one valid value from the enumeration.

So my guess is that your RootElement class defines attrWithEnum as a single enum instead of as a list of enum ( List<AttrEnum> )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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