问题
I have an XSD which defines a hierarchy of several complex types (each one being a child of the other).
Ex:
<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>
I'm looking to import only complexType FlawType
into a list. I figure I can probably use Apache Digester to do this but was wondering if there was some way to do this with JAXB. Unmarshalling direct to a detailedreport
object and then using loops to extract the FlawType is feasible, but seems like a lot of extra work.
In essence, I'm hoping to be able to come up with a solution that would do something like:
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 );
I could probably load the entire XML file into a DOM object, then use something like XPath to locate all the individual FlawType
nodes and for each node, use an Unmarshaller to do it for each node, but didn't know if there was an easier way. I presume I might be able to use some form of a SAX Parser as well (I've never used them) but was hoping for something a little more straight forward.
I'm actually using the Spring 4 framework with spring-oxm package to handle a lot of the JAXB legwork for me, so would love to find a simple solution that will be easily understood and maintainable. Using something like Digester just adds more technology to my stack which I would much rather avoid.
Is there an easy way to do this with JAXB, or this is beyond the scope of JAXB?
回答1:
I have managed to find the following as a solution, but don't think it is the prettiest possible:
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);
I was hoping for something a little neater. For starters, I do not like the idea that I have to manually search for element named cwe
. I would, at the very least, like to be able to get the element name from the generated CweType class or the CategoryType class, but the only way I can see doing that is reflection. Is that the only way?
来源:https://stackoverflow.com/questions/32773969/jaxb-is-there-a-way-to-unmarshal-only-specific-paths-in-an-xml