1 <?php
2 /**
3 * XAO_DomFactory.php
4 *
5 * This script provides the class definition for DomFactory - a class which is
6 * used to safely return DOM XML objects.
7 *
8 * @author Terence Kearns
9 * @version 0.2
10 * @copyright Terence Kearns 2003
11 * @license LGPL
12 * @link http://xao-php.sourceforge.net
13 * @package XAO
14 */
15
16 /**
17 * Import the root (base) XAO class.
18 *
19 * All classes in the XAO library should have this class at the top of their
20 * inheritance tree. See documentation on the class itself for more details.
21 * Including the following DomDoc class will automatically include the XaoRoot
22 * definition, however, it is included here for clarity and completeness.
23 *
24 * @import XaoRoot
25 */
26 include_once "XAO_XaoRoot.php";
27
28 /**
29 * Import the text debugging facility.
30 *
31 * This class provides an HTML output facility for displaying a portion of text
32 * with one line highlighted. It is used by DomFactory when it throws
33 * an exception.
34 *
35 * @import TextDebugger
36 */
37 include_once "XAO_TextDebugger.php";
38
39 /**
40 * Quick XML Parser and Debugger
41 *
42 * This main job of this class is to test for XML well-formedness. Secondly, it
43 * is to provide highly useful debugging output in the event that the input text
44 * fails the wellformedness test.
45 *
46 * @package XAO
47 */
48 class DomFactory extends XaoRoot {
49
50 var $objDoc;
51
52 var $intErrorLine;
53
54 var $uriContextFile;
55
56 var $strErrorMsg;
57
58 var $strErrorMsgFull;
59
60 function DomFactory($strTarget) {
61 if(strstr($strTarget,"\n") === false) {
62 if(file_exists($strTarget)) {
63 $this->objDoc = $this->_objDomParseFile($strTarget);
64 return;
65 }
66 }
67 $this->objDoc =& $this->_objDomParseData($strTarget);
68 }
69
70 function &objGetObjDoc() {
71 return $this->objDoc;
72 }
73
74 function &_objDomParseFile($uriSrc) {
75 // assume that the file does not exist
76 $this->uriContextFile = null;
77 if(file_exists($uriSrc)) {
78 // populate $this->uriContextFile for
79 // use later in _objDomParseData()
80 $this->uriContextFile = $uriSrc;
81 // try to keep all file access thread-
82 // safe when obtaining the content.
83 // This is the main reason we don't use
84 // domxml_open_file() - it does not
85 // participate in flock() co-operative
86 // locking.
87 $fp = fopen($uriSrc,"r")
88 OR $this->Throw(
89 "\nCould not open ".$uriSrc,
90 $this->arrSetErrFnc(__FUNCTION__,__LINE__)
91 );
92 flock($fp,LOCK_SH)
93 OR $this->Throw(
94 "\nCould not get a shared lock on ".$uriSrc.".",
95 $this->arrSetErrFnc(__FUNCTION__,__LINE__)
96 );
97 $strFileData = fread($fp,filesize($uriSrc));
98 flock($fp,LOCK_UN);
99 fclose($fp);
100 // We now have the content. Parse it.
101 // And exit the fuction.
102 return $this->_objDomParseData($strFileData);
103 }
104 else {
105 $this->Throw(
106 "\nFile (".$uriSrc.") not found.",
107 $this->arrSetErrFnc(__FUNCTION__,__LINE__)
108 );
109 }
110 return false;
111 }
112
113 function &_objDomParseData($strSrc) {
114 // Attempt a new DOM object using
115 // supplied data. Suppress errors.
116 $objDoc = @domxml_open_mem($strSrc);
117 // test for success. if parse fails, we
118 // are obligated to produce error
119 // information.
120 if(!is_object($objDoc)) {
121
122 $strFile = "";
123 if(strlen($this->uriContextFile))
124 $strFile = " in file ".$this->uriContextFile." ";
125 // We only go to the bother of
126 // performing another [sax] parse if
127 // we failed the initial DOM parse.
128 if($this->blnSaxParse($strSrc)) {
129 // DOM parse failed, SAX parse succeded.
130 // We need DOM parsing to succeed.
131 // Throw appropriate error.
132 $this->Throw(
133 "The XML data ".$strFile
134 ."was parsed by PHP's XML parser but not by "
135 ."PHP's DOM XML domxml_open_mem() method. No details of the "
136 ."error can be extracted from domxml_open_mem(). Sorry.",
137 $this->arrSetErrFnc(__FUNCTION__,__LINE__)
138 );
139 }
140 else {
141 // While we expected the SAX parse to
142 // fail also, it did the job of
143 // providing the error information that
144 // we could not extract from DOM
145 $this->Throw(
146 $this->strErrorMsgFull.$this->strDebugData,
147 $this->arrSetErrFnc(__FUNCTION__,__LINE__)
148 );
149 }
150 return false;
151 }
152 return $objDoc;
153 }
154
155 function blnSaxParse($strData) {
156 $xp = xml_parser_create();
157 //xml_set_object($xp, $this);
158 $xpRes = xml_parse($xp,$strData);
159 if(!$xpRes) {
160 $this->strErrorMsg = xml_error_string(xml_get_error_code($xp));
161 $this->intErrorLine = xml_get_current_line_number($xp);
162
163 $this->strErrorMsgFull = "The following parse error occured";
164 if($this->intErrorLine !== false) {
165 $this->strErrorMsgFull .=
166 " on or near line ".$this->intErrorLine;
167 }
168 if(strlen($this->uriContextFile)) {
169 $this->strErrorMsgFull .=
170 " in the file ".$this->uriContextFile;
171 }
172 $this->strErrorMsgFull .= ":\n ".$this->strErrorMsg."\n";
173
174 if(is_int($this->intErrorLine)) {
175 $objDebugData =& new TextDebugger(
176 $strData,
177 $this->
178 intErrorLine );
179 $this->strDebugData = $objDebugData->strGetHtml();
180 }
181 }
182 xml_parser_free($xp);
183 return $xpRes;
184 }
185
186 function Throw($strErrMsg,$arrErrAttribs) {
187 parent::Throw($strErrMsg,$arrErrAttribs);
188 if($this->intErrorLine)
189 $arrErrAttribs["line"] = $this->intErrorLine;
190 if(strlen(trim($this->strDebugData)))
191 die("<br />\n".$this->strError.$this->strDebugData);
192 }
193 }
194
195 ?>