【问题标题】:spring-oxm: Can I unmarshall a subelement of a file?spring-oxm:我可以解组文件的子元素吗?
【发布时间】:2015-12-23 15:31:17
【问题描述】:

这与my prior question 有关,后者通常更针对 JAXB。但是这个问题更具体地与spring-oxm 中的解组器相关。我正在寻找是否可以使用 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);

但是,如果我尝试使用 spring-oxm unmarshaller 的概念,则会出现错误。

    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 在 cmets 中建议尝试 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 unmarshaller显式声明declaredType?

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;
    ...
    ....

【问题讨论】:

  • 为什么?只需使用编组器并使用 XPath 表达式来检索您想要的元素。无需自己修改文档。
  • @M.Deinum 最终结果不一样吗? XPath 只会返回我想要的元素,然后仍然需要解组它们。正是解组导致了我的问题——我质疑它是否是 b/c,DeclaredType 没有用 @XMLRootElement 注释,并且无法明确地向 spring-oxm 编组器指示声明的类型,它无法确定哪个输入它。但这只是猜测。
  • 该路径将正常工作,而无需在您周围进行任何黑客攻击,您正在尝试绕过框架而不是使用框架。
  • @M.Deinum 是使用原始 XPath 还是 Spring 内部的东西? B/c 如果我尝试使用基本 XPath,我会收到相同的错误(我已更新问题以包括我尝试使用 XPath)。

标签: java xml spring jaxb spring-oxm


【解决方案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));

我希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多