// Setup
$dom = new DOMDocument;
$dom->formatOutput = TRUE;
$dom->preserveWhiteSpace = FALSE;
$dom->loadXML('<pages/>');
// How to set a valid id attribute when not using a DTD or Schema
$page1 = $dom->createElement('page');
$page1->setAttribute('xml:id', 'p1');
$page1->appendChild($dom->createElement('product', 'foo1'));
$page1->appendChild($dom->createElement('product', 'foo2'));
// How to set an ID attribute that requires a DTD or Schema when reloaded
$page2 = $dom->createElement('page');
$page2->setAttribute('id', 'p2');
$page2->setIdAttribute('id', TRUE);
$page2->appendChild($dom->createElement('product', 'bar1'));
$page2->appendChild($dom->createElement('product', 'bar2'));
// Appending pages and saving XML
$dom->documentElement->appendChild($page1);
$dom->documentElement->appendChild($page2);
$xml = $dom->saveXML();
unset($dom, $page1, $page2);
echo $xml;
这将创建一个这样的XML文件:当你在XML再次读取
<?xml version="1.0"?>
<pages>
<page xml:id="p1">
<product>foo1</product>
<product>foo2</product>
</page>
<page id="p2">
<product>bar1</product>
<product>bar2</product>
</page>
</pages>
,新的DOM实例不再知道您已声明非名称空间id
属性作为ID属性与setIdAttribute
。它仍然在XML中,但id属性只是一个常规属性。 You have to be aware that ID attributes are special in XML.
// Load the XML we created above
$dom = new DOMDocument;
$dom->loadXML($xml);
现在对于一些测试:
echo "\n\n GETELEMENTBYID RETURNS ELEMENT WITH XML:ID \n\n";
foreach($dom->getElementById('p1')->childNodes as $product) {
echo $product->nodeValue; // Will output foo1 and foo2 with whitespace
}
上述工作,因为DOM的解析器必须承认xml:id
是一个ID属性,无论任何DTD或模式。这在上面链接的规格中有解释。 输出空白的原因是由于格式化输出在开始标记,两个产品标记和结束标记之间存在DOMText节点,所以我们正在遍历五个节点。在使用XML时,节点概念对理解至关重要。
echo "\n\n GETELEMENTBYID CANNOT FETCH NORMAL ID \n\n";
foreach($dom->getElementById('p2')->childNodes as $product) {
echo $product->nodeValue; // Will output a NOTICE and a WARNING
}
以上将不起作用,因为id
不是ID属性。为了使DOM解析器能够识别它,您需要一个DTD或Schema,并且必须根据它对XML进行验证。在另一方面
echo "\n\n XPATH CAN FETCH NORMAL ID \n\n";
$xPath = new DOMXPath($dom);
$page2 = $xPath->query('/pages/page[@id="p2"]')->item(0);
foreach($page2->childNodes as $product) {
echo $product->nodeValue; // Will output bar1 and bar2
}
XPath是文字有关的属性,这意味着你可以查询DOM的网页元素与属性id
如果getElementById
不可用。请注意,要查询ID为p1的页面,你必须包含命名空间,例如@xml:id="p1"
。
echo "\n\n XPATH CAN FETCH PRODUCTS FOR PAGE WITH ID \n\n";
$xPath = new DOMXPath($dom);
foreach($xPath->query('/pages/page[@id="p2"]/product') as $product) {
echo $product->nodeValue; // Will output bar1 and bar2 w\out whitespace
}
就像上面说的,你也可以用XPath来查询文档中的其他内容。这个将不会输出空格,因为它只会返回页面下方的product
元素,其ID为p2。
您还可以遍历节点中的整个DOM。这是一个树形结构。由于DOMNode是DOM中最重要的类,因此您需要熟悉它。
echo "\n\n TRAVERSING UP AND DOWN \n\n";
$product = $dom->getElementsByTagName('product')->item(2);
echo $product->tagName; // 'product'
echo $dom->saveXML($product); // '<product>bar1</product>'
// Going from bar1 to foo1
$product = $product->parentNode // Page Node
->parentNode // Pages Node
->childNodes->item(1) // Page p1
->childNodes->item(1); // 1st Product
echo $product->nodeValue; // 'foo1'
// from foo1 to foo2 it is two(!) nodes because the XML is formatted
echo $product->nextSibling->nodeName; // '#text' with whitespace and linebreak
echo $product->nextSibling->nextSibling->nodeName; // 'product'
echo $product->nextSibling->nextSibling->nodeValue; // 'foo2'
在旁注上,是的,我在上面的原始代码中有一个错字。它是product
而不是products
。但是我发现,当你必须改变的是s
时,声称代码不起作用是没有道理的。这只是感觉太想要被舀。
我假设你刚才给出了你的XML文档的结构大纲?因为它不是XML你发布的(我只是想确定;))。 – 2010-08-04 11:45:22
当然这只是一个大纲。 XML验证很好,看起来不错,不像我的代码:o – fabrik 2010-08-04 11:59:14
simplexml函数对于您的需求太简单了吗? – stillstanding 2010-08-04 12:11:44