NMTOKENS
类型是由空格字符分隔的NMTOKEN
列表。问题是我无法将值解组为complexType的List
。
我使用JAXB创建了对象模型,A
类型的生成源为内容List<Serializable>
,而TestSimpleList
为List<String>
。
public class A {
@XmlMixed
protected List<Serializable> content;
@XmlAttribute(name = "a", required = true)
@XmlSchemaType(name = "anySimpleType")
protected String a;
public class UseCase {
@XmlList
@XmlElement(name = "TestSimpleList", required = true)
@XmlSchemaType(name = "NMTOKENS")
protected List<String> testSimpleList;
编组按预期工作,因此如果我向内容添加多个值,这些值将被序列化为由空格字符分隔的字符串。但它不适用于解组,List<Serializable>
只包含一个由空格字符分隔的String
元素。
您可以使用以下架构和测试用例测试问题:
有效的XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<UseCase xmlns="urn:xxx/1">
<TestSimpleList>a b</TestSimpleList>
<TestComplexList a="a">a b</TestComplexList>
</UseCase>
相应的架构:
<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xxx/1"
xmlns:a="urn:xxx/1"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<element name="UseCase">
<complexType>
<sequence>
<element name="TestSimpleList" type="a:SimpleList"></element>
<element name="TestComplexList" type="a:ComplexList"></element>
</sequence>
</complexType>
</element>
<simpleType name="SimpleList">
<restriction base="NMTOKENS"></restriction>
</simpleType>
<complexType name="ComplexList">
<simpleContent>
<restriction base="a:A">
<simpleType>
<restriction base="NMTOKENS"/>
</simpleType>
</restriction>
</simpleContent>
</complexType>
<complexType name="A" mixed="true">
<attribute name="a" use="required"/>
</complexType>
</schema>
JAXB绑定:
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings generateMixedExtensions="true"/>
<jaxb:bindings scd="x-schema::a" xmlns:a="urn:xxx/1">
<jaxb:schemaBindings>
<jaxb:package name="com.example.demo.tools.domain"/>
</jaxb:schemaBindings>
</jaxb:bindings>
</jaxb:bindings>
测试用例:
package com.example.demo.tools;
import com.example.demo.tools.domain.ComplexList;
import com.example.demo.tools.domain.UseCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import static org.junit.Assert.assertEquals;
@RunWith(MockitoJUnitRunner.class)
public class JaxbTest {
@Test
public void marshall() throws JAXBException {
JAXBContext contextObj = JAXBContext.newInstance(UseCase.class);
Marshaller marshaller = contextObj.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
UseCase useCase = new UseCase();
useCase.getTestSimpleList().add("a");
useCase.getTestSimpleList().add("b");
ComplexList complexList = new ComplexList();
complexList.setA("a");
complexList.getContent().add("a");
complexList.getContent().add("b");
useCase.setTestComplexList(complexList);
StringWriter sw = new StringWriter();
marshaller.marshal(useCase, sw);
System.out.println("sw = " + sw);
}
@Test
public void unmarshall() throws JAXBException {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
"<UseCase xmlns=\"urn:xxx/1\">" +
"<TestSimpleList>a b</TestSimpleList>" +
"<TestComplexList a=\"a\">a b</TestComplexList>" +
"</UseCase>";
JAXBContext contextObj = JAXBContext.newInstance(UseCase.class);
Unmarshaller unmarshaller = contextObj.createUnmarshaller();
UseCase useCase = (UseCase) unmarshaller.unmarshal(new StringReader(xml));
assertEquals(2, useCase.getTestSimpleList().size());
// The following assertion fails
assertEquals(2, useCase.getTestComplexList().getContent().size());
}
}