3

我有以下 XML 代码:

<CampaignFrameResponse
  xmlns="http://Qsurv/api"
  xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Message>Success</Message>
  <Status>Success</Status>
  <FrameHeight>308</FrameHeight>   
  <FrameUrl>http://delivery.usurv.com?Key=a5018c85-222a-4444-a0ca-b85c42f3757d&amp;ReturnUrl=http%3a%2f%2flocalhost%3a8080%2feveningstar%2fhome</FrameUrl> 
</CampaignFrameResponse>

我想要做的是提取节点并将它们分配给一个变量。例如,我有一个名为FrameHeight包含 value的变量308

这是我到目前为止的Java代码:

private void processNode(Node node) {
    NodeList nodeList = node.getChildNodes();
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node currentNode = nodeList.item(i);
       if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
            //calls this method for all the children which is Element
            LOG.warning("current node name: " + currentNode.getNodeName());
            LOG.warning("current node type: " + currentNode.getNodeType());
            LOG.warning("current node value: " + currentNode.getNodeValue());
            processNode(currentNode);
       }
    }

}

这会打印出节点名称、类型和值,但是将每个值分配给适当命名的变量的最佳方法是什么?例如int FrameHeight = 308

这是我更新的代码,其中 nodeValue 变量不断返回 null:

processNode(Node node) {
NodeList nodeList = node.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
    Node currentNode = nodeList.item(i);
    if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
        //calls this method for all the children which is Element
        String nodeName = currentNode.getNodeName();
        String nodeValue = currentNode.getNodeValue();
        if(nodeName.equals("Message")) {
            LOG.warning("nodeName: " + nodeName); 
            message = nodeValue;
            LOG.warning("Message: " + message); 
        } 
        else if(nodeName.equals("FrameHeight")) {
            LOG.warning("nodeName: " + nodeName); 
            frameHeight = nodeValue;
            LOG.warning("frameHeight: " + frameHeight);
        }
        processNode(currentNode);
    }
}

}

4

6 回答 6

2

您可以使用DOM, SAX, Pull-Parser,但最好使用以下 API。

- JAXP & JAXB

- Castor

例如:DOM 解析

DocumentBuilderFactory odbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder odb =  odbf.newDocumentBuilder();
            InputSource is = new InputSource(new StringReader(xml));
            Document odoc = odb.parse(is);
            odoc.getDocumentElement().normalize ();    // normalize text representation
            System.out.println ("Root element of the doc is " + odoc.getDocumentElement().getNodeName());
            NodeList LOP = odoc.getElementsByTagName("response");

                Node FPN =LOP.item(0);
                try{
                if(FPN.getNodeType() == Node.ELEMENT_NODE)
                    {

                    Element token = (Element)FPN;

                    NodeList oNameList1 = token.getElementsByTagName("user_id");
                    Element firstNameElement = (Element)oNameList1.item(0);
                    NodeList textNList1 = firstNameElement.getChildNodes();
                    this.setUser_follower_id(Integer.parseInt(((Node)textNList1.item(0)).getNodeValue().trim()));
                    System.out.println("#####The Parsed data#####");
                    System.out.println("user_id : " + ((Node)textNList1.item(0)).getNodeValue().trim());
                    System.out.println("#####The Parsed data#####");
于 2012-10-11T10:28:25.903 回答
2

我在 Java 中使用 XML 已经有一段时间了(超过十年),并尝试了许多替代方法(自定义文本解析、专有 API、SAX、DOM、Xmlbeans、JAXB 等)。我学到了两件事:

  • 坚持标准。切勿使用专有 API,而应使用标准 Java API(JAXP,包括 SAX、DOM、Stax 等)。您的代码将更具可移植性和可维护性,并且不会在 XML 库的某个版本发生更改和破坏兼容性时发生更改(这种情况经常发生)。
  • 花点时间学习 XML 技术。我建议您至少了解 XSD、XSLT 和 XPath(XSLT 需要)的全面知识。如果你没有时间,那么专注于 XSD。
  • 尽可能利用自动 XML 代码生成/解析。这意味着了解 XSD。从长远来看,它回报了最初的努力,随着时间的推移,代码更易于维护,解析/编组得到了极大的优化(通常比使用“手动”JAXP API 更优化)和 XML 验证(你已经拥有 XSD)可以执行(更少的检查代码,安全的格式错误的 XML 使您的应用程序崩溃,更少的集成工作)。最棒的是,您只需编写 XSD 代码,几乎所有处理数据所需的 Java 代码(Java Bean)都会为您生成。

Knowadays 每当我必须解析一些这样的 XML 时,我倾向于使用代码生成。其标准是 JAXB(xmlbeans 已死,其他替代品可能没有成熟或广泛使用)。在您的情况下,我将定义一个 XSD,尽可能详细地定义您的文档(即,如果您使用只能有多个值的字符串,请不要使用“xs:string”类型,而是使用枚举类型)。它可能看起来像这样:

<xs:schema attributeFormDefault="unqualified"
    elementFormDefault="qualified" targetNamespace="http://Qsurv/api"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="CampaignFrameResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element type="xs:string" name="Message" />
                <xs:element type="Status" name="Status" />
                <xs:element type="xs:short" name="FrameHeight" />
                <xs:element type="xs:anyURI" name="FrameUrl" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <<xs:simpleType name="Status">
        <xs:annotation>
            <xs:appinfo>
                <jaxb:typesafeEnumClass>
                    <jaxb:typesafeEnumMember name="SUCCESS"
                        value="Success" />
                    <jaxb:typesafeEnumMember name="FAILURE"
                        value="Failure" />
                </jaxb:typesafeEnumClass>
            </xs:appinfo>
        </xs:annotation>
        <xs:restriction base="xs:string">
            <xs:enumeration value="Success" />
            <xs:enumeration value="Failure" />
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

现在是使用 JAXB 工具(请参阅 xjc 编译器选项)生成代码并查看有关如何将生成的 Java Bean 从/到 XML 编组/解组的一对示例。

于 2012-10-11T11:03:03.580 回答
1

Xstream 在您的情况下不支持,它可用于将对象转换为 xml 然后再返回。如果您的 xml 是从 CampaignFrameResponse 类的实例生成的,您可以使用 xstream。

否则,您只需检查

String nodeName = currentNode.getNodeName()
String nodeValue = currentNode.getNodeValue() ;
if( nodeName.equals("Message")){
     message = nodeValue ;
} else if( nodeName.equals("FrameHeight") {
     frameHeight = nodeValue ;
}

如果需要 int 值,则需要解析。

于 2012-10-11T10:48:48.387 回答
1

您当然可以创建名称-值映射并在遍历 XML 时更新映射。在解析结束时,您可以在地图中查找特定的键。Java 不允许您以编程方式创建变量,因此您将无法根据 XML 数据生成具有其名称的变量。

除了样式和可读性之外,您从 XML 填充数据结构的决定取决于 XML 的定义有多完善以及它的模式将来可能会改变多少。您可以问自己以下问题:节点名称将来可以更改吗?是否可以引入限制本节的 XML 小节?这可能会帮助您选择特定的解析器(SAX/DOM 或更高级别的对象解析 API)。

当然,如果您无法控制 XML 定义,那么除了解析已有的内容外,您几乎无能为力。

于 2012-10-11T11:23:43.830 回答
0

我不建议直接解析 xml(除非您被迫这样做),而是使用外部库,例如http://x-stream.github.io/。这个想法是您可以创建一个代表您的 xml 模式的对象,并且库将为您填充该对象。

于 2012-10-11T10:32:20.993 回答
0

我建议使用 - x-stream.github.io - 带有一些分界注释,您可以非常快速地从 XML 创建对象,而编码很少。

于 2012-10-11T10:32:43.643 回答