使用默认命名空间读取 XML
Reading XML with default namespace
考虑这份工作:
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>
至:
<tests xmlns="xyz">
现在无法读取任何内容。
如何使用默认命名空间读取 XML?
你可以通过 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());
}
}
另一种方法,空白根的 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 的第一个解决方案。
考虑这份工作:
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>
至:
<tests xmlns="xyz">
现在无法读取任何内容。
如何使用默认命名空间读取 XML?
你可以通过 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());
}
}
另一种方法,空白根的 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 的第一个解决方案。