2013-02-17 55 views
6

मैं एक पार्सर लिखने की प्रक्रिया में हूं, और अपवादों के साथ अच्छी त्रुटि प्रबंधन करने की कोशिश कर रहा हूं।अमान्य दस्तावेज़ों में PHP त्रुटियों को फेंकने के लिए PHP के XMLReader को प्राप्त करना

निम्नलिखित नमूना कोड:

<?php 
$xml = <<<XML 
<?xml version="1.0"?> 
<rootElem> 
XML; 

$reader = new XMLReader(); 
$reader->xml($xml, null, LIBXML_NOERROR | LIBXML_NOWARNING); 

$reader->read(); 

का उत्सर्जन करता है:

PHP Warning: XMLReader::read(): An Error Occured while reading in /Users/evert/code/xml/errortest.php on line 11 
PHP Stack trace: 
PHP 1. {main}() /Users/evert/code/xml/errortest.php:0 
PHP 2. XMLReader->read() /Users/evert/code/xml/errortest.php:11 

के अलावा:

libxml_use_internal_errors(true); 

कोई प्रभाव नहीं।

मेरा लक्ष्य बाद में त्रुटियों की जांच करना है (libxml_get_errors() के साथ), और अपवाद फेंक दें। मुझे लगता है कि एकमात्र समाधान चुप्पी (@) ऑपरेटर का प्रयोग होता है, लेकिन यह एक बुरा विचार की तरह लगता है ..

ध्यान दें कि जब मैं LIBXML स्थिरांक उत्तीर्ण नहीं होते हैं, और न ही libxml_use_internal_errors उपयोग करते हैं, मुझे कोई दूसरी त्रुटि प्राप्त , जैसे:

PHP Warning: XMLReader::read(): /Users/evert/code/xml/:2: parser error : Extra content at the end of the document in /Users/evert/code/xml/errortest.php on line 11 

यह पता चलता है कि अंतर्निहित libxml पुस्तकालय वास्तव में त्रुटि दबाकर है, लेकिन XMLReader भीतर एक त्रुटि वैसे भी फेंक दिया है।

+0

त्रुटियों का ट्रैक रखने के लिए शायद 'try' और 'catch' लागू करें? – Anne

+1

हालांकि वे अपवाद नहीं हैं, वे पारंपरिक PHP त्रुटियां हैं। कोशिश करने का एकमात्र तरीका मैं कोशिश कर सकता हूं, 'set_error_handler' के साथ है, जिसे मैं पुस्तकालय लिख रहा हूं, क्योंकि मैं वैश्विक राज्य को बदलना नहीं चाहता हूं। – Evert

उत्तर

4

ऐसा लगता है कि तुलना में read() के लिए @ उपयोग करने के लिए, php स्रोत के बाद से अन्य चेतावनी को दबाने के लिए कोई रास्ता नहीं है लाइनों निम्नलिखित गया है जैसे:

retval = xmlTextReaderRead(intern->ptr); 
if (retval == -1) { 
    php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occured while reading"); 
    RETURN_FALSE; 
} else { 
    RETURN_BOOL(retval); 
} 

तो, xmlTextReaderRead() अंदर केवल वास्तविक पार्सिंग त्रुटि द्वारा दबा दिया जा रहा है libxml_use_internal_errors(true); या विकल्प XMLReader::xml() पर पास हुए।

+3

बहुत दुर्भाग्यपूर्ण; मुझे एक ही पंक्तियां मिलीं और इसके लिए टिकट खोला गया: https://bugs.php.net/bug.php?id=64230 – Evert

+0

यहां तक ​​कि @ मेरे लिए काम नहीं लग रहा है - मैंने की कोशिश की जबकि (@ $ x -> पढ़ें()) {...} और मुझे अभी भी एक त्रुटि संदेश मिलता है। –

3

मेरी समझ से XMLReader, दस्तावेज़ को सत्यापित करने के लिए, सभी दस्तावेज़ों के माध्यम से एक पूर्ण पास आयोजित करना होगा।

क्या मैं कर रहा हूँ है:

// Enable internal libxml errors 
libxml_use_internal_errors(true); 
$xml = new \XMLReader(); 
$xsd='myfile.xsd'; 
$xml->open('myfile.xml'); 
$xml->setSchema ($xsd); 

// Conduct full pass through document. The only reason is to force validation. 
while (@$xml->read()) { }; // empty loop 

if (count(libxml_get_errors())==0) { 
    echo "provided xml is well formed and xsd-valid"; 
    // Now you can start processing without @ as document was validated against xsd and is xml-wellformed 
} 
else 
    echo "provided xml is wrong and/or not xsd-valid. stopping"; 
बेशक आप खाली लूप के अंदर त्रुटियों के लिए जाँच कर सकते हैं और फिर पहली त्रुटि के बाद तुरंत तोड़ने के

। मैंने देखा है कि XMLReader पहली त्रुटि के बाद पूरी तरह विफल नहीं होता है - यह जारी रहता है और उपयोगी मुद्दों की सरणी लाता है। कभी-कभी पहली समस्या के बाद ब्रेक प्रोसेसिंग के बजाय पाए गए सभी मुद्दों को मुद्रित करने के लिए उपयोगी हो सकता है।

मेरी सबसे बड़ी चिंता XMLVeader में है वैध कार्य मौजूद है :) मुझे लगता है कि यह वास्तव में एक प्रकार का कामकाज है लेकिन यह 95% XMLReader उपयोग मामलों के प्रसंस्करण से पहले बहुत अच्छी तरह से काम करता है और इसका सत्यापन करता है क्योंकि इसका उपयोग बड़े पैमाने पर किया जाता है एक्सएमएल संग्रह प्रसंस्करण।