从xml文档对象

时间:2018-02-12 05:51:52

标签: java xml xml-parsing

我们从xml文件创建Document对象如下。

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse("D:/ABC.xml");
            document.normalize();

从创建的文档逻辑中获取子节点如下所示。

public void getDataFromXML()
{
            Node rootElement = document.getDocumentElement();
            int childsCount = rootElement.getChildNodes().getLength();
            for(index = 0; index < childsCount; index ++ )
            {
                Node item = rootElement.getChildNodes().item(index);

                printXMLNode(item);
             }
   }



    public synchronized void printXMLNode(Node xmlNode)
    {
            int nodesLength = xmlNode.getChildNodes().getLength();
            System.out.println("XML-DEBUG : "+xmlNode);
            for(int attribCount = 0; attribCount < nodesLength; ++ attribCount)
            {
                    Node attribute = xmlNode.getChildNodes().item(attribCount);
                    System.out.println("\t\t "+attribCount+" "+attribute);
            }
    }

两个线程试图从不同的地方调用相同的方法:      一个线程调用的Ex在下面:

Thread test = new Thread(){
  public void run()
  {
  while(true)
   {
    getDataFromXML();                          
      }    
   }         
    };                 
    test.start();

输入XML是:

     <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE Script SYSTEM "Script.dtd">
<Script>
<setValue>
<Label>User Name</Label>
<Value>sysadmin</Value>
</setValue>
<setValue>
<Label>Password</Label>
<Value>XXX</Value>
</setValue>
<click>
<Label>Login</Label>
</click>
<click>
<Label>Purchasing Super User</Label>
</click>
<click>
<Label>Requisitions[1]</Label>
</click>
<click>
<Label>Requisitions[2]</Label>
</click>
<SetText>
<Value>Vision Operations</Value>
</SetText>
<KeyPress>
<Label>Operating Unit0</Label>
</KeyPress>
<SetText>
<Value>Purchase Requisition</Value>
</SetText>
<KeyPress>
<Label>Type0</Label>
</KeyPress>
<SetText>
<Label>Description</Label>
<Value/>
<Disable>True</Disable>
<Comment/>
</SetText>
<KeyPress>
<Label>Description0</Label>
</KeyPress>
</Script>

方法(printXMLNode)的输出在某些节点的不同时间会有所不同(每次都不适用于同一节点)。 有时候,预期的结果会出现,但有时却没有。

例如,对于SetText节点,预期输出为:

XML-DEBUG : [SetText: null]
0 [#text: 
1 [Value: null]
2 [#text:

Strage输出是:

XML-DEBUG : [SetText: null]
     0 [setValue: null]
     1 [setValue: null]
     2 [click: null]
     3 [click: null]
     4 [click: null]
     5 [click: null]
     6 [SetText: null]
     7 [KeyPress: null]
     8 [SetText: null]
     9 [KeyPress: null]
     10 [SetText: null]
     11 [KeyPress: null]

无法理解为什么结果会发生变化。很少有线程尝试从此方法获取数据,这就是为什么我们将此方法保持为同步,即使问题仍然存在。 有人可以帮帮忙吗?

1 个答案:

答案 0 :(得分:0)

正如您似乎意识到的那样,DOM不是线程安全的。您已经同步了一个访问DOM的方法,但是您的方法getDataFromXML也使用DOM方法并且未同步。

如果您需要多线程,则有比DOM更好的API。如果所有线程都只是读取,JDOM2和XOM都是线程安全的(我相信)。

更好的是,在XQuery或XSLT中完成所有工作。