java - JAXB:有没有办法只解码 XML 中的特定路径?

标签 java xml spring jaxb spring-oxm

我有一个 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:complexType name="FlawType">
  <xs:sequence>
    <xs:element name="mitigations" minOccurs="0" maxOccurs="1" type="tns:MitigationListType" />
    <xs:element name="exploit_desc" type="tns:LongTextType" minOccurs="0" maxOccurs="1"/>
  </xs:sequence>
</xs:complexType>


<xs:complexType name="MitigationListType">
  <xs:sequence>
    <xs:element name="mitigation" minOccurs="0" maxOccurs="unbounded" type="tns:MitigationType"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="MitigationType">
  <xs:attribute name="action" type="xs:string" use="required"/>
  <xs:attribute name="description" type="xs:string" use="required"/>
  <xs:attribute name="user" type="xs:string" use="required"/>
  <xs:attribute name="date" type="xs:string" use="required"/>
</xs:complexType>

</xs:schema>

我希望仅将complexType FlawType 导入到列表中。我想我可能可以使用 Apache Digester 来完成此操作,但想知道是否有某种方法可以使用 JAXB 来完成此操作。直接解码到 detailedreport 对象,然后使用循环来提取 FlawType 是可行的,但似乎需要大量额外工作。

本质上,我希望能够提出一个解决方案,可以执行以下操作:

   String xml = FileUtils.readFileToString( XML_File );
   unmarshaller = JAXBContext.createUnmarshaller();
   // only unmarhsal nodes of FlawType.class from the xml file.
   List<FlawType> flawTypes = unmarshaller.unmarshal( xml, FlawType.class );

我可能可以将整个 XML 文件加载到 DOM 对象中,然后使用 XPath 之类的东西来定位所有单独的 FlawType 节点,并对于每个节点,使用 Unmarshaller 为每个节点执行此操作,但不知道是否有更简单的方法。我想我也许也可以使用某种形式的 SAX 解析器(我从未使用过它们),但希望能有更直接的东西。

我实际上使用带有 spring-oxm 包的 Spring 4 框架来为我处理大量的 JAXB 跑腿工作,所以很想找到一个易于理解和维护的简单解决方案。使用像 Digester 这样的东西只会为我的堆栈添加更多技术,而我宁愿避免这种技术。

是否有一种简单的方法可以使用 JAXB 执行此操作,或者这超出了 JAXB 的范围?

最佳答案

我设法找到以下解决方案,但认为这不是最漂亮的解决方案:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder(); 
Document doc = db.parse(IOUtils.toInputStream(xml));
NodeList nodeList = doc.getElementsByTagName("cwe");

JAXBContext jc = JAXBContext.newInstance( CweType.class );
Unmarshaller u = jc.createUnmarshaller();

List<CweType> cwes = new ArrayList<>();
for( int i = 0; i < nodeList.getLength(); i++ )
    cwes.add( u.unmarshal(nodeList.item(i),  CweType.class);

我希望有一些更简洁的东西。首先,我不喜欢必须手动搜索名为 cwe 的元素。至少,我希望能够从生成的 CweType 类或 CategoryType 类中获取元素名称,但我认为这样做的唯一方法是反射。这是唯一的方法吗?

关于java - JAXB:有没有办法只解码 XML 中的特定路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32773969/

相关文章:

java - 通过 JobParameter 在 Spring Batch 中设置属性文件

java - C++ 的 const 成员函数的 Java 等价物是什么?

spring - 使用 spring 读取 war 之外的属性文件

spring - 在 Spring 中以编程方式访问启用 SSL 的 Tomcat 上的 Web 应用程序 API

java - Spring + Maven + Hadoop

java - 在 @Configuration 类中的 Spring 中设置注释驱动的事务

java - Spring:访问 JSP 下拉列表中的模型属性列表

c++ - opencv - haarcascades 不适用于眼睛检测

xml - 如何使用 xml 设置图像按钮的选定状态

python - 使用 python 在现有 xml 文档中插入 xml 节点