spring-oxm: Могу ли я распаковать подэлемент файла?

Это связано с моим предыдущим вопросом, который был больше направлен на 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;
    ...
    ....

person Eric B.    schedule 25.09.2015    source источник
comment
Почему? Просто используйте маршаллер и выражение XPath для извлечения нужных элементов. Не нужно самостоятельно возиться с документом.   -  person M. Deinum    schedule 25.09.2015
comment
@ M.Deinum Конечный результат не будет таким же? XPath просто вернет нужные мне элементы, а затем все равно придется их разбирать. Это неупорядочивание вызывает у меня проблему - я задаюсь вопросом, связано ли это с тем, что DeclaredType не аннотирован с помощью @XMLRootElement и, не имея возможности явно указать объявленный тип маршаллеру spring-oxm, он не может определить, какой тип он является. Но это всего лишь предположение.   -  person Eric B.    schedule 25.09.2015
comment
Путь будет просто работать без каких-либо взломов, когда вы пытаетесь обойти фреймворк, а не работать с фреймворком.   -  person M. Deinum    schedule 25.09.2015
comment
@ M.Deinum M.Deinum использует необработанный XPath или что-то изнутри Spring? B/c, если я попытаюсь использовать базовый XPath, я получу ту же ошибку (я обновил вопрос, чтобы включить мою попытку использовать XPath).   -  person Eric B.    schedule 25.09.2015


Ответы (1)


 public static CweType unmarshal(DOMSource node) throws JAXBException {
    JAXBContext jaxbContext = JAXBContext.newInstance(CweType.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

    JAXBElement<CweType> root = jaxbUnmarshaller.unmarshal(node, CweType.class);
    CweType cweType= root.getValue();

    LOGGER.info(cweType.toString());
    return cweType;
}

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder(); 
Document doc = db.parse(IOUtils.toInputStream(xml));
NodeList nodeList = doc.getElementsByTagName("cwe");
CweType type = unmarshal(new DOMSource(nodeList.item(0));

Я надеюсь, что это может быть полезно!

person Lazar Lazarov    schedule 25.04.2016