在Java中解析XML以提取所有节点&属性

时间:2015-04-10 10:54:27

标签: java xml

我遇到了一个问题,试图解析一些XML文档以获得我需要的输出。

获取此示例XML:



<root>
      <ZoneRule Name="After" RequiresApproval="false">
         <Zone>
            <WSAZone ConsecutiveDayNumber="1">
               <DaysOfWeek>
                  <WSADaysOfWeek Saturday="false"/>
               </DaysOfWeek>
               <SelectedLimits>
               </SelectedLimits>
               <SelectedHolidays>
               </SelectedHolidays>
            </WSAZone>
         </Zone>
      </ZoneRule>
	  <ZoneRule Name="Before" RequiresApproval="false">
         <Zone>
            <WSAZone ConsecutiveDayNumber="3">
               <DaysOfWeek>
                  <WSADaysOfWeek Saturday="true"/>
               </DaysOfWeek>
               <SelectedLimits>
               </SelectedLimits>
               <SelectedHolidays>
               </SelectedHolidays>
            </WSAZone>
         </Zone>
      </ZoneRule>
</root>
&#13;
&#13;
&#13;

我试图做的是能够忽略根标签(这在这里没有问题),并且对待每个&#34; ZoneRule&#34;作为自己的个体块。

一旦我将每个ZoneRule隔离,我需要提取所有节点和属性,以允许我创建一个字符串来查询数据库以检查它是否存在(这部分也在工作)。

我遇到的问题是,在我的代码中,我无法将每个单独的ZoneRule块分开,出于某种原因,它被一起处理。

我的示例代码如下:

&#13;
&#13;
public String testXML = "";
int andCount = 0;

public void printNote(NodeList nodeList) {

    for (int count = 0; count < nodeList.getLength(); count++) {

        Node tempNode = nodeList.item(count);

        // make sure it's element node.
        if (tempNode.getNodeType() == Node.ELEMENT_NODE) {
            if (tempNode.hasAttributes()))) {
                // get attributes names and values
                NamedNodeMap nodeMap = tempNode.getAttributes();

                for (int i = 0; i < nodeMap.getLength(); i++) {
                    Node node = nodeMap.item(i);
                    if (andCount == 0) {
                        testXML = testXML + "XMLDataAsXML.exist('//" + tempNode.getNodeName() + "[./@" + node.getNodeName() + "=\"" + node.getNodeValue() + "\"]')=1 \n";
                    } else {
                        testXML = testXML + " and XMLDataAsXML.exist('//" + tempNode.getNodeName() + "[./@" + node.getNodeName() + "=\"" + node.getNodeValue() + "\"]')=1 \n";
                    }
                    andCount = andCount + 1;
                }
            }
            if (tempNode.hasChildNodes()) {
                // loop again if has child nodes
                printNote(tempNode.getChildNodes());
            }
        }
    }

}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        try {
            File file = new File("C:\\Test.xml");
            DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = dBuilder.parse(file);
            //System.out.println("Root element :" + doc.getDocumentElement().getNodeName());

            if (doc.hasChildNodes()) {
                printNote(doc.getChildNodes());
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        System.out.println(testXML);

    }
&#13;
&#13;
&#13;

产生此输出(两个节点组合)。

XMLDataAsXML.exist('//ZoneRule[./@Name="After"]')=1 
 and XMLDataAsXML.exist('//ZoneRule[./@RequiresApproval="false"]')=1 
 and XMLDataAsXML.exist('//WSAZone[./@ConsecutiveDayNumber="1"]')=1 
 and XMLDataAsXML.exist('//WSADaysOfWeek[./@Saturday="false"]')=1 
 and XMLDataAsXML.exist('//ZoneRule[./@Name="Before"]')=1 
 and XMLDataAsXML.exist('//ZoneRule[./@RequiresApproval="false"]')=1 
 and XMLDataAsXML.exist('//WSAZone[./@ConsecutiveDayNumber="3"]')=1 
 and XMLDataAsXML.exist('//WSADaysOfWeek[./@Saturday="true"]')=1 

我实际上是这样的(借口不完整的SQL语句):

XMLDataAsXML.exist('//ZoneRule[./@Name="After"]')=1 
 and XMLDataAsXML.exist('//ZoneRule[./@RequiresApproval="false"]')=1 
 and XMLDataAsXML.exist('//WSAZone[./@ConsecutiveDayNumber="1"]')=1 
 and XMLDataAsXML.exist('//WSADaysOfWeek[./@Saturday="false"]')=1 


XMLDataAsXML.exist XMLDataAsXML.exist('//ZoneRule[./@Name="Before"]')=1 
 and XMLDataAsXML.exist('//ZoneRule[./@RequiresApproval="false"]')=1 
 and XMLDataAsXML.exist('//WSAZone[./@ConsecutiveDayNumber="3"]')=1 
 and XMLDataAsXML.exist('//WSADaysOfWeek[./@Saturday="true"]')=1 

将要解析的XML并不总是如上所述,所以我不能使用硬编码的xPaths等 - 我需要动态循环遍历文档,寻找ZoneRule节点作为我的基础(我将动态生成此值基于收到的文件)然后提取所有必需的信息。

我完全乐于接受比上述尝试更好的方法。

非常感谢。

1 个答案:

答案 0 :(得分:0)

在您的代码中,testXMLandCountprintNote方法之外声明,并且在迭代期间不会被重置。

你从第一个ZoneRule开始,在第一个迭代期间生成正确的文本(让我们忘记递归),现在你移动到下一个ZoneRule,但是testXML包含整个生成的文本,而theCount则是大于0,所以你继续附上为下一个ZoneRule生成的文本。

您应该在for循环的每个iteriation的初始化时重置andCount和testXML。但是那时你会递归'儿童不能正确呈现。

所以要么你需要两个方法来处理顶层的ZoneRule元素而另一个用于它的子节点,或者更好,而不是将文本追加到共享变量,你应该重新设置你的方法,这样它们就会返回String值,然后就可以了在递归调用时正确地附加(使用或不使用新行或不使用)。