2010-08-25 7 views
6

यह उत्तर देने के लिए एक बहुत ही आसान सवाल की तरह लगता है लेकिन मैं इसे काम करने में सक्षम नहीं हूं। मैं PHP 5.2.6 चला रहा हूँ।मैं PHP डॉम में किसी तत्व का नामस्थान कैसे ढूंढ सकता हूं?

मैं (मूल तत्व), जो है, जब मैं $ तत्व-> saveXML() के लिए जाना, यह एक xmlns विशेषता आउटपुट एक डोम तत्व है:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> 
... 

हालांकि, मैं प्रोग्राम के रूप में के भीतर किसी भी तरह से नहीं मिल सकता है नामस्थान को देखने के लिए PHP। मैं यह जांचने में सक्षम होना चाहता हूं कि यह मौजूद है या नहीं और यह क्या सेट है।

$document->documentElement->namespaceURI की जांच करना स्पष्ट उत्तर होगा लेकिन यह खाली है (मैं वास्तव में इसे खाली नहीं होने में सक्षम हूं)। उत्पादन में xmlns मान उत्पन्न कर रहा है और मैं इसे कैसे पढ़ सकता हूं?

एकमात्र व्यावहारिक तरीका मैं अब तक ऐसा करने में सक्षम हूं - इसे saveXML() का उपयोग करके स्ट्रिंग में एक्सएमएल के रूप में सहेजकर, फिर नियमित अभिव्यक्तियों का उपयोग करके इसे पढ़कर।

संपादित करें:

यह loadHTML (का उपयोग करने में लोड हो रहा है XML की एक विशेष लक्षण हो सकता है) बल्कि loadXML() और फिर से saveXML का उपयोग कर इसे बाहर मुद्रण()। जब आप ऐसा करते हैं, तो ऐसा लगता है कि किसी कारण से saveXML एक xmlns विशेषता जोड़ता है, भले ही यह पता लगाने का कोई तरीका न हो कि यह xmlns मान DOM विधियों का उपयोग कर दस्तावेज़ का हिस्सा है। जो मुझे लगता है कि अगर मुझे यह पता लगाने का कोई तरीका था कि क्या लोड किया गया दस्तावेज़ लोड HTML() का उपयोग करने में लोड किया गया था, तो मैं इसे एक अलग तरीके से हल कर सकता हूं।

उत्तर

5

Like edorian already showed, मार्कअप loadXML के साथ लोड होने पर नामस्थान ठीक काम करता है। लेकिन तुम सही है कि मार्कअप के लिए इस अभ्यस्त काम loadHTML के साथ भरी हुई हैं:

$html = <<< XML 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="foo" lang="en"> 
    <body xmlns="foo">Bar</body> 
</html> 
XML; 

$dom = new DOMDocument; 
$dom->loadHTML($html); 

var_dump($dom->documentElement->getAttribute("xmlns")); 
var_dump($dom->documentElement->lookupNamespaceURI(NULL)); 
var_dump($dom->documentElement->namespaceURI); 

खाली परिणाम देगा।लेकिन आप XPath

$xp = new DOMXPath($dom); 
echo $xp->evaluate('string(@xmlns)'); 
// http://www.w3.org/1999/xhtml; 

और शरीर

echo $xp->evaluate('string(body/@xmlns)'); // foo 

या संदर्भ नोड के साथ के लिए उपयोग कर सकते हैं

$body = $dom->documentElement->childNodes->item(0); 
echo $xp->evaluate('string(@xmlns)', $body); 
// foo 

मेरे अशिक्षित धारणा है कि आंतरिक रूप से, एक HTML दस्तावेज़ एक असली से अलग है दस्तावेज़। आंतरिक libxml uses a different module to parse HTML और DOMDocument ही है, एक अलग nodeType का हो जाएगा के रूप में आप बस 13 किया जा रहा है एक XML_HTML_DOCUMENT_NODE साथ

var_dump($dom->nodeType); // 13 with loadHTML, 9 with loadXml 

करके सत्यापित कर सकते हैं।

+0

बहुत अच्छा और विस्तृत, पार्सिंग विधि के आधार पर नोड टाइप के बारे में नहीं पता था, लेकिन यह समझ में आता है – edorian

+0

नोडटाइप के बारे में संकेत और xpath का उपयोग करने की क्षमता के लिए धन्यवाद - मेरी कई समस्याओं को हल करता है! – thomasrutter

3

पीएचपी 5.2.6 के साथ मैं यह करने के लिए 2 तरीके पाया है:

<?php 
$xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?'. 
     '><html xmlns="http://www.w3.org/1999/xhtml" lang="en"></html>'; 
$x = DomDocument::loadXml($xml); 
var_dump($x->documentElement->getAttribute("xmlns")); 
var_dump($x->documentElement->lookupNamespaceURI(NULL)); 

प्रिंट

string(28) "http://www.w3.org/1999/xhtml" 
string(28) "http://www.w3.org/1999/xhtml" 

आशा thats तुम :)

+0

आपके उत्तर के लिए धन्यवाद - यह मेरी समस्या का समाधान नहीं करता है लेकिन मुझे यह सुझाव देता है कि यह loadXML() के बजाय लोड HTML() से लोड किए गए दस्तावेज़ों के लिए कुछ असाधारण प्रतीत होता है क्योंकि वास्तव में, आपका उदाहरण loadXML() के साथ काम करता है। ऐसा लगता है कि लोड HTML एक "अदृश्य नेमस्पेस" वाले दस्तावेज़ बनाता है जिसे DOM विधियों का उपयोग करके पढ़ा नहीं जा सकता है, लेकिन जब आप saveXML() सहेजते हैं तो दिखाई देता है। – thomasrutter

+0

मुझे यकीन नहीं है कि मैं 100% का अनुसरण कर सकता हूं लेकिन loadHtml के साथ कुछ लोड कर रहा हूं और saveXml के माध्यम से इसे सहेजना मेरे लिए xmlns नहीं जोड़ता है। यह सिर्फ एचटीएमएल से एक डॉक्टरेट जोड़ता है/संरक्षित करता है। हो सकता है कि अगर आप आउटपुट के साथ थोड़ा पुन: उत्पन्न स्क्रिप्ट प्रदान कर सकते हैं तो मैं गहराई से – edorian

+0

ख़राब कर सकता हूं दिलचस्प - यह कभी-कभी करता है और कभी-कभी नहीं करता है। यदि आपके इनपुट एचटीएमएल दस्तावेज़ में एक्सएचटीएमएल डॉक्टरेट है, तो यह करता है। यह इस इनपुट के लिए करेगा: thomasrutter

1

के लिए क्या पूछा ठीक है, आप कर सकते हैं तो इस तरह के एक समारोह के साथ:

function getNamespaces(DomNode $node, $recurse = false) { 
    $namespaces = array(); 
    if ($node->namespaceURI) { 
     $namespaces[] = $node->namespaceURI; 
    } 
    if ($node instanceof DomElement && $node->hasAttribute('xmlns')) { 
     $namespaces[] = $xmlns = $node->getAttribute('xmlns'); 
     foreach ($node->attributes as $attr) { 
      if ($attr->namespaceURI == $xmlns) { 
       $namespaces[] = $attr->value; 
       } 
     } 
    } 
    if ($recurse && $node instanceof DomElement) { 
     foreach ($node->childNodes as $child) { 
      $namespaces = array_merge($namespaces, getNamespaces($child, vtrue)); 
     } 
    } 
    return array_unique($namespaces); 
} 

तो, आप इसे एक DomEelement फ़ीड, और फिर इसे सभी संबंधित नामस्थान पाता है:

$xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <html xmlns="http://www.w3.org/1999/xhtml" 
     lang="en" 
     xmlns:foo="http://example.com/bar"> 
      <body> 
       <h1>foo</h1> 
       <foo:h2>bar</foo:h2> 
      </body> 
</html>'; 
var_dump(getNamespaces($dom->documentElement, true)); 

प्रिंटों आउट:

array(2) { 
    [0]=> 
    string(28) "http://www.w3.org/1999/xhtml" 
    [3]=> 
    string(22) "http://example.com/bar" 
} 

ध्यान दें कि DOMDocument स्वचालित रूप से सभी अप्रयुक्त नामस्थान नहीं हटेगा ...

क्यों $dom->documentElement->namespaceURI हमेशा null है, ऐसा इसलिए है क्योंकि दस्तावेज़ तत्व में नामस्थान नहीं है। xmlns विशेषता दस्तावेज़ के लिए एक डिफ़ॉल्ट नेमस्पेस प्रदान करती है, लेकिन यह नामस्थान के साथ html टैग (DOM इंटरैक्शन के प्रयोजनों के लिए) को समाप्त नहीं करती है। आप $dom->documentElement->removeAttribute('xmlns') करने का प्रयास कर सकते हैं, लेकिन अगर यह काम करेगा तो मुझे 100% यकीन नहीं है ...

संबंधित मुद्दे