使用默认命名空间读取XML

3
考虑一下这份工作的工作内容:
static void XMLTest(Args _args)
{
    str xml = @'<?xml version="1.0" encoding="UTF-8"?>
       <tests xmlns="abc">
           <test>
               <testnumber><id>1</id></testnumber>
               <testname>bla bla</testname>
           </test>
       </tests>
   ';
   XMlDocument doc = XMLDocument::newXML(xml);
   XMLNodeList tests = doc.selectNodes('//tests/test');
   XMLNode node;
   for (node = tests.nextNode(); node; node = tests.nextNode())
   {
       info(node.selectSingleNode('testnumber/id').text());
       info(node.selectSingleNode('testname').text());
   }
}

我将按照预期输出"1"和"bla bla"。

现在更改xml的第二行:

<tests>

to:

<tests xmlns="xyz">

现在它无法读取任何内容。

如何读取带有默认命名空间的XML?

2个回答

4
你可以通过 XMLNamespaceManager 实例的严格方式来完成它。
static void XMLTest(Args _args)
{
    str xml = @'<?xml version="1.0" encoding="UTF-8"?>
       <tests xmlns="abc">
           <test>
               <testnumber><id>1</id></testnumber>
               <testname>bla bla</testname>
           </test>
       </tests>
   ';
   XMlDocument doc = XMLDocument::newXML(xml);
   XMLNamespaceManager nsMgr = new XMLNamespaceManager(new XmlNameTable());
   XMLNodeList tests;
   XMLNode node;
   ;

   nsMgr.addNamespace('x', 'abc');
   tests = doc.selectNodes("//x:tests/x:test", nsMgr);

   for (node = tests.nextNode(); node; node = tests.nextNode())
   {
       info(node.selectSingleNode('x:testnumber/x:id', nsMgr).text());
       info(node.selectSingleNode('x:testname', nsMgr).text());
   }
}

如果确定不会出现命名冲突,您可以忽略命名空间,并通过 local-name() 匹配节点。
static void XMLTest2(Args _args)
{
    str xml = @'<?xml version="1.0" encoding="UTF-8"?>
       <tests xmlns="abc">
           <test>
               <testnumber><id>1</id></testnumber>
               <testname>bla bla</testname>
           </test>
       </tests>
   ';
   XMlDocument doc = XMLDocument::newXML(xml);
   XMLNodeList tests = doc.selectNodes("//*[local-name()='tests']/*[local-name()='test']");
   XMLNode node;
   for (node = tests.nextNode(); node; node = tests.nextNode())
   {
       info(node.selectSingleNode("*[local-name()='testnumber']/*[local-name()='id']").text());
       info(node.selectSingleNode("*[local-name()='testname']").text());
   }
}

0

另一种方法是将根元素的xmlns属性留空:

static void XMLTest(Args _args)
{
    str xml = @'<?xml version="1.0" encoding="UTF-8"?>
       <tests xmlns="abc">
           <test>
               <testnumber><id>1</id></testnumber>
               <testname>bla bla</testname>
           </test>
       </tests>
   ';
   XMlDocument doc = XMLDocument::newXML(xml);
   XMLNodeList tests;
   XMLNode node;
   ;
   doc.root().attributes().getNamedItem('xmlns').value(''); // Go away xmlns
   doc = XMLDocument::newXML(doc.xml());                    // Now reread all again
   tests = doc.selectNodes("//tests/x:test", nsMgr);   
   for (node = tests.nextNode(); node; node = tests.nextNode())
   {
       info(node.selectSingleNode('testnumber/id').text());
       info(node.selectSingleNode('testname'.text());
   }
}

这需要使用doc = XMLDocument::newXML(doc.xml())重新解析XML。如果XML很大,请选择@DAXaholic的第一个解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接