Это связано с моим предыдущим вопросом, который был больше направлен на JAXB в целом. Но этот вопрос больше связан конкретно с немаршаллером в spring-oxm
. Я хочу посмотреть, смогу ли я использовать unmarshaller spring-oxm для демаршалирования только определенных элементов из моего XML.
Мой XSD:
<xs:schema version="1.3"
targetNamespace="https://www.domain.com/schema/reports/export/1.0"
xmlns:tns="https://www.domain.com/schema/reports/export/1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="detailedreport">
<xs:complexType>
<xs:sequence>
<xs:element name="severity" minOccurs="6" maxOccurs="6" type="tns:SeverityType" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="SeverityType">
<xs:sequence>
<xs:element name="category" minOccurs="0" maxOccurs="unbounded" type="tns:CategoryType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="CategoryType">
<xs:sequence>
<xs:element name="cwe" maxOccurs="unbounded" type="tns:CweType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="CweType">
<xs:sequence>
<xs:element name="staticflaws" type="tns:FlawListType" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="FlawListType">
<xs:sequence>
<xs:element name="flaw" minOccurs="0" maxOccurs="unbounded" type="tns:FlawType" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Используя некоторую предварительную обработку, я могу найти все узлы типа «cwe»:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(IOUtils.toInputStream(xml));
NodeList nodeList = doc.getElementsByTagName("cwe");
Используя JAXBUnmarshaller, я могу разобрать свой объект:
JAXBContext jc = JAXBContext.newInstance( CweType.class );
Unmarshaller u = jc.createUnmarshaller();
u.unmarshal(new DOMSource(nodeList.item(0)), CweType.class);
Однако, если я попытаюсь использовать концепцию unmarshaller spring-oxm, я получу ошибку.
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setClassesToBeBound(CweType.class);
jaxb2Marshaller.unmarshal(new DOMSource(nodeList.item(0)));
org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"cwe"). Expected elements are (none)
at org.springframework.oxm.jaxb.Jaxb2Marshaller.convertJaxbException(Jaxb2Marshaller.java:911)
at org.springframework.oxm.jaxb.Jaxb2Marshaller.unmarshal(Jaxb2Marshaller.java:784)
at org.springframework.oxm.jaxb.Jaxb2Marshaller.unmarshal(Jaxb2Marshaller.java:753)
@M.Deinum предложил в комментариях попробовать XPath, но я не опасался лучшего - выдает ту же ошибку в неуправляемое время:
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList xpnl = (NodeList)xPath.compile("//cwe").evaluate(doc, XPathConstants.NODESET);
jaxb2Marshaller.unmarshal(new DOMSource(xpnl.item(0)));
Что я делаю неправильно? Что-то не так с тем, как я создаю свой DOMSource()? Почему я могу распаковать с помощью JAXBUnmarshaller напрямую, но не с помощью оболочки Spring? Есть ли способ явно объявить через демаршаллер spring-oxm объявленный тип?
CweType.java:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "CweType", propOrder = {
"description",
"staticflaws",
"dynamicflaws",
"manualflaws"
})
public class CweType {
@XmlElement(required = true)
protected CweType.Description description;
protected FlawListType staticflaws;
protected FlawListType dynamicflaws;
protected FlawListType manualflaws;
@XmlAttribute(name = "cweid", required = true)
@XmlSchemaType(name = "positiveInteger")
protected BigInteger cweid;
...
....
spring-oxm
, он не может определить, какой тип он является. Но это всего лишь предположение. - person Eric B.   schedule 25.09.2015