Stax API XML 解析产生空结果

Stax API XML parsing produces null results

一段时间以来,我一直在努力解决这个问题,但收效甚微。现在,我真的别无选择。我会感谢一些帮助或指向正确方向的指示....因为我相信我做的不是很好。

用下面的代码解析后,我在大多数字段中都有空值:Result{id=30c26c8a-8bdf-4d4d-8f8d-a19661f16877, name=Andriod_Office_Task, owner =generated.Owner@53d8d10a, comment=, creationTime=2016-09-09T19:30, modificationTime=2016-09-09T19:30:05+02:00, reportId=null, taskid=null, host=null, port=null, nvt=null, scanNVTVersion=null, threat=null, severity=null, description=null}

解析方法(为简洁起见排除其他方法):

private List<Result> readDocument(XMLStreamReader parser) throws         XMLStreamException, DatatypeConfigurationException {
    List<Result> results = new ArrayList<>();

    while (parser.hasNext()) {
        int eventType = parser.next();
        switch (eventType) {
        case XMLStreamReader.START_ELEMENT:
            String elementName = parser.getLocalName();
            if (elementName.equals("result"))
                results.add(readResult(parser));
            break;
        case XMLStreamReader.END_ELEMENT:
            return results;

        }
    }
    throw new XMLStreamException("Premature end of file");
}

public Result readResult(XMLStreamReader parser) throws XMLStreamException, DatatypeConfigurationException {

    Result result = new Result();
    result.setId(parser.getAttributeValue(null, "id"));


    Report report = new Report();

    Task task = new Task();

    while (parser.hasNext()) {
        int eventType = parser.next();
        switch (eventType) {
        case XMLStreamReader.START_ELEMENT:
            String elementName = parser.getLocalName();
            if (elementName.equals("name"))
                result.setName(readCharacters(parser));
            else if (elementName.equals("host"))
                result.setHost(readCharacters(parser));
            else if (elementName.equals("owner"))
                result.setOwner(readOwner(parser));
            else if (elementName.equals("comment"))
                result.setComment(readCharacters(parser));
            else if (elementName.equals("creation_time"))

                result.setCreationTime(readCreationTime(parser));

            else if (elementName.equals("modification_time"))
                result.setModificationTime(readCharacters(parser));
            else if (elementName.equals("report"))
                report.setId(readReport(parser));
            else if (elementName.equals("task"))
                task.setId(readTask(parser));
            else if (elementName.equals("user_tags"))
                result.setUserTags(readUserTags(parser));
            else if (elementName.equals("port"))
                result.setPort(readCharacters(parser));
            else if (elementName.equals("nvt"))
                result.setNvt(readNvt(parser));
            else if (elementName.equals("scan_nvt_version"))
                result.setScanNVTVersion(readCharacters(parser));
            else if (elementName.equals("threat"))
                result.setThreat(readCharacters(parser));
            else if (elementName.equals("severity"))
                result.setSeverity(readCharacters(parser));
            else if (elementName.equals("qod"))
                result.setQod((Qod) readQod(parser));
            else if (elementName.equals("description"))
                result.setDescription(readCharacters(parser));

            break;
        case XMLStreamReader.END_ELEMENT:
        }
        return result;

    }

    throw new XMLStreamException("Premature end of file");
}

private String readCharacters(XMLStreamReader reader) throws XMLStreamException {
    StringBuilder result = new StringBuilder();
    while (reader.hasNext()) {
        int eventType = reader.next();
        switch (eventType) {
        case XMLStreamReader.CHARACTERS:
            result.append(reader.getText());
            break;
        case XMLStreamReader.END_ELEMENT:
            return result.toString();
        }
    }
    throw new XMLStreamException("Premature end of file");
}


}

结果 class 如下:

   @XmlRootElement
   @XmlAccessorType(XmlAccessType.FIELD)
   @JsonIgnoreProperties(ignoreUnknown = true)
   public class Result {

@XmlAttribute
private String id;

 @XmlElement
 private String name;

@XmlElement
private Task task;

@XmlElement
private String comment;

@XmlElement(name = "creation_time")
String creationTime;

@XmlElement(name = "modification_time")
private String modificationTime;

// TODO user_tags
@XmlElement
private UserTags userTags;

@XmlElement
private Owner owner;

@XmlElement
private Qod qod;

/**
 * // * The report the result belongs to (only when details were requested)
 * //
 */
@XmlElementWrapper(name = "report")
@XmlElement(name = "reportId")
private String reportId;

@XmlElement
private String host;

@XmlElement
private String port;

@XmlElement
private NVT nvt;

@XmlElement(name = "scan_nvt_version")
private String scanNVTVersion;

@XmlElement
private String threat;

@XmlElement
private String severity;

@XmlElement
private String description;

public Result() {
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}



public Task getTask() {
    return task;
}


public void setTask(Task task) {
    this.task = task;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getComment() {
    return comment;
}

public void setComment(String comment) {
    this.comment = comment;
}

public String getCreationTime() {
    return creationTime;
}

public void setCreationTime(String creationTime) {
    this.creationTime = creationTime;
}

public String getModificationTime() {
    return modificationTime;
}

public void setModificationTime(String modificationTime) {
    this.modificationTime = modificationTime;
}

public UserTags getUserTags() {
    return userTags;
}

public void setUserTags(UserTags userTags) {
    this.userTags = userTags;
}

public Qod getQod() {
    return qod;
}

public void setQod(Qod qod) {
    this.qod = qod;
}

public Owner getOwner() {
    return owner;
}

public void setOwner(Owner owner) {
    this.owner = owner;
}

public String getReportId() {
    return reportId;
}

public void setReportId(String reportId) {
    this.reportId = reportId;
}



public String getHost() {
    return host;
}

public void setHost(String host) {
    this.host = host;
}

public String getPort() {
    return port;
}

public void setPort(String port) {
    this.port = port;
}

public NVT getNvt() {
    return nvt;
}

public void setNvt(NVT nvt) {
    this.nvt = nvt;
}

public String getScanNVTVersion() {
    return scanNVTVersion;
}

public void setScanNVTVersion(String scanNVTVersion) {
    this.scanNVTVersion = scanNVTVersion;
}

public String getThreat() {
    return threat;
}

public void setThreat(String threat) {
    this.threat = threat;
}

public String getSeverity() {
    return severity;
}

public void setSeverity(String severity) {
    this.severity = severity;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

@Override
public String toString() {
    return "Result{" + "id=" + id +
     ", name=" + name + ", owner =" + owner +
            ", comment=" + comment + ", creationTime=" + creationTime + ", modificationTime=" + modificationTime
            + ", reportId=" + reportId + ", taskid=" + task + ", host=" + host + ", port=" + port + ", nvt=" + nvt
            + ", scanNVTVersion=" + scanNVTVersion + ", threat=" + threat + ", severity=" + severity
            + ", description=" + description + '}';
}

}
<get_results_response status="200" status_text="OK">
    <result id="30c26c8a-8bdf-4d4d-8f8d-a19661f16877">
        <name>Trace route</name>
        <owner>
            <name>admin</name>
        </owner>
        <comment/>
        <creation_time>2016-09-09T19:30:05+02:00</creation_time>
        <modification_time>2016-09-09T19:30:05+02:00</modification_time>
        <  id="2a6d7f75-f6b7-40b2-a792-b558fada375b"/>
        <task id="e59ac66b-5b59-4756-bace-37bb1106276d">
            <name>Andriod_Office_Task</name>
        </task>
        <user_tags>
            <count>0</count>re
        </user_tags>
        <host>172.16.53.178</host>
        <port>general/tcp</port>
        <nvt oid="1.3.6.1.4.1.25623.1.0.51662">
            <name>Traceroute</name>
            <family>General</family>
            <cvss_base>0.0</cvss_base>
            <cve>NOCVE</cve>
            <bid>NOBID</bid>
            <xref>NOXREF</xref>
            <tags>cvss_base_vector=AV:N/AC:L/Au:N/C:N/I:N/A:N|qod_type=remote_banner|solution=Block unwanted packets from escaping your network.|summary=A traceroute from the scanning server to the target system was
conducted. This traceroute is provided primarily for informational
value only. In the vast majority of cases, it does not represent a
vulnerability. However, if the displayed traceroute contains any
private addresses that should not have been publicly visible, then you
have an issue you need to correct.</tags>
            <cert/>
        </nvt>
        <scan_nvt_version>$Revision: 2837 $</scan_nvt_version>
        <threat>Log</threat>
        <severity>0.0</severity>
        <qod>
            <value>80</value>
            <type>remote_banner</type>
        </qod>
        <description>Here is the route from 192.168.14.128 to 172.16.53.178:

192.168.14.128
172.16.53.178</description>
    </result>
    <filters id="">
        <term>first=1 rows=-1 sort=name</term>
        <keywords>
            <keyword>
                <column>first</column>
                <relation>=</relation>
                <value>1</value>
            </keyword>
            <keyword>
                <column>rows</column>
                <relation>=</relation>
                <value>-1</value>
            </keyword>
            <keyword>
                <column>sort</column>
                <relation>=</relation>
                <value>name</value>
            </keyword>
        </keywords>
    </filters>
    <sort>
        <field>name
            <order>ascending</order></field>
    </sort>
    <results max="-1" start="1"/>
    <result_count>3444
        <filtered>1</filtered>
        <page>1</page></result_count>
</get_results_response>

经过一些研究并尝试使用一些常见的 xml 解析方法,我最终使用了 jackson-dataformat-xml approach。虽然这可能不是最好的,但它用更少的代码给了我想要的东西。基本上,我必须调整模型 classes 中的注释,如下所示:

 @JsonIgnoreProperties(ignoreUnknown=true)
 @JacksonXmlRootElement(localName = "results")
 public class Results {


@JacksonXmlProperty(localName = "result")
@JacksonXmlElementWrapper(useWrapping = false)
public Result [] result;


public Results() {
        }


public Result[] getResult() {
    return result;
}


public void setResult(Result[] result) {
    this.result = result;
}


@Override
public String toString() {
    return "Results [result=" + Arrays.toString(result) + "]";
}

以及对解析的一些改编 class:

public class GetReportsResponseHandler extends   DefaultHandler<GetReportsResponse> {

private XmlMapper mapper = new XmlMapper();
public GetReportsResponseHandler() {
super(new GetReportsResponse(), "get_reports_response");
AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
AnnotationIntrospector secondary = new JaxbAnnotationIntrospector();
AnnotationIntrospector pair = new AnnotationIntrospectorPair(primary,         secondary);
mapper.setAnnotationIntrospector(pair);
}

@Override
protected void parseStartElement(XMLStreamReader parser) throws    XMLStreamException, IOException {
    if ("report".equals(parser.getName().toString())){
        Report report = mapper.readValue(parser, Report.class);
        response.addReport(report);
    }