[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Editing XML dynamically and using two input XML fi
thei wrote:
Hello, <snip/> I discovered that there was no DOM method in PHP for "grafting" an XML fragment into another XML document. I also got no response from comp.lang.php on the issue. I imagine it is easy to do in XSLT but I wanted to import XML fragements into my DOM object instance. Basically I wrote a wrapper class for PHP's DOM functionality and included a method called ImportChildFrag($ndStub,$ndNew) check out the last three methods in this class definition. (this code will eventually be release when it is actually tested). Generally you would use this class by inheriting it. <?php include_once "class_xmlErrorLog.php"; // Each of the following constants // represent different ways to // interperet the first constructor // argument. // creates a new dom document from // scratch define("DOMDOC_AS_NEW",10); // creates a dom object from file URI. // uses non-exclusive read locking. define("DOMDOC_AS_READFILE",20); // creates a dom object from file URI. // uses exclusive write locking. define("DOMDOC_AS_WRITEFILE",30); // creates a dom object from remote // file URI (read-only). define("DOMDOC_AS_REMOTEFILE",40); // uses start param as a reference to // and existing DOM document object define("DOMDOC_AS_REFERENCE",50); // uses start param as data of new dom // document. define("DOMDOC_AS_DATA",60); /** * General purpose DOM class * * This class provides three forms of functionality. 1) shortcut functions to * operations made tedious by the DOM API. 2) additional features not supported * by the DOM API. 3) a thread-safe way of interacting with files associated * with the class' DOM document. * * @author Terence Kearns * @version 0.0.1 * @copyright Terence Kearns * @license LGPL * @homepage http://terencekearns.com */ class domDoc { /** * An instance of xmlErrorLog used by this class. * * @access private * @var object */ var $objErr; /** * An instance of a DOM XML object. * * @access public * @var object */ var $objDoc; /** * Document root * * @access public * @var object */ var $ndRoot; /** * Is the document read-only * * @access public * @var boolean */ var $blnIsReadOnly; /** * How has the document been instantiated. What mode. * * @access private * @var integer from constant */ var $intMode; /** * File Pointer * * This is used if the mode is WRITABLE so that the file resource is opened * (and locked) in the contructor the unlocked and closed in a sepaerate * member function (commit()). * * @access private * @var integer from constant */ var $fp; /** * Constructor method * * Create the objDoc instance property and associated ndRoot property based * on the user-selected mode of document creation. In the process, establish * the blnIsReadOnly property. * * @param mixed information required to create a DOM document * @param int constant specifying how the document is to be created * @return void */ function domDoc(&$Starter,$intUse = DOMDOC_AS_NEW) { $this->objErr = new xmlErrorLog($this); $this->intMode = $intUse; $this->blnIsReadOnly = true; // for more info on each case block, see // comments in the constant definitions // at the top of this file. switch ($intUse) { case DOMDOC_AS_NEW: $this->blnIsReadOnly = false; $this->objDoc = domxml_new_doc("1.0"); $elRoot = $this->objDoc->create_element($Starter); $this->ndRoot = $this->objDoc->append_child($elRoot); break; case DOMDOC_AS_READFILE: $fp = fopen($Starter,"r") OR $this->throw( "could not open ".$Starter." for reading." ); // attempt thread safety by using flock flock($fp,LOCK_SH); $xmlData = fread($fp,filesize($Starter)); flock($fp,LOCK_UN); fclose($fp); // finish working with the file as // quickly as possible and THEN worry // about making a DOM doc from it. $this->_domOpenFromData($xmlData); break; case DOMDOC_AS_WRITEFILE: $this->blnIsReadOnly = false; $this->fp = fopen($Starter,"r+b") OR $this->throw( "could not open ".$Starter." for writing." ); flock($this->fp,LOCK_EX); $xmlData = fread($this->fp,filesize($Starter)); $this->_domOpenFromData($xmlData,$Starter); break; case DOMDOC_AS_REMOTEFILE: $fp = fopen($Starter,"r") OR $this->throw( "could not open ".$Starter." for reading." ); $xmlData = fread($fp,filesize($Starter)); fclose($fp); $this->_domOpenFromData($xmlData); break; case DOMDOC_AS_REFERENCE: $this->objDoc =& $Starter; break; case DOMDOC_AS_DATA: $this->_domOpenFromData($Starter); break; default: $this->throw( "second argument to domDoc constructor is invalid" ); } } /** * Serialise and return the entire document object as a stand-alone XML. * * @return xml well formed ascii * @access private */ function _domOpenFromData(&$xmlData,$Starter = null) { if(!trim($xmlData)) { $this->objDoc = domxml_new_doc("1.0"); $ndRoot = $this->objDoc->create_element("emptyDocument"); $this->ndRoot = $this->objDoc->append_child($ndRoot); if($this->intMode == DOMDOC_AS_WRITEFILE) { // clean up the dangling resource flock($this->fp,LOCK_UN); fclose($this->fp); // register an error $this->throw($Starter." is empty."); } else { // register an error $this->throw("requested document is empty."); } // do not continue this function return; } $this->objDoc = domxml_open_mem($xmlData); if(!is_object($this->objDoc)) { $this->throw("Could not create an XML document using:\n\n".$xmlData); return; } $this->ndRoot = $this->objDoc->document_element(); } function throw($strErrMsg) { $this->objErr->trap($strErrMsg); $this->ConsumeDoc($this->objErr); } function _AbortDocument($strErrMsg) { // populate the DOM doc with an // error message. $this->objDoc = domxml_new_doc("1,0"); $nd = $this->objDoc->create_element("error"); $this->ndRoot = $this->objDoc->append_child($nd); $this->ndRoot->set_content($strErrMsg); $this->ndRoot->set_attribute("ts",time()); } /** * Serialise and return the entire document object as a stand-alone XML. * * @return xml document * @access public */ function xmlGetDoc() { return $this->objDoc->dump_mem(true); } /** * Serialise and return the entire document as a well-balenced XML fragment. * * @return xml fragment * @access public */ function xmlGetFrag() { return "\n\n".$this->objDoc->dump_node($this->ndRoot,true)."\n\n"; } /** * Insert stylesheet processing instruction * * * @param uri path to XSL stylesheet. * @return bool success */ function AddStylePI($uriStylesheet) { $strPiCont = ' type="text/xsl" href="'.$uriStylesheet.'"'; $strPiTarget = 'xml-stylesheet'; $piNode = $this->objDoc->create_processing_instruction($strPiTarget, $strPiCont); $this->objDoc->insert_before($piNode, $this->ndRoot); return true; } /** * mass storage serialisation * * This function will dump the textual contents of the DOM document (in it's * current state to) file. * * @param uri path to destination file * @return bool success or failure */ function Commit() { if($this->intMode == DOMDOC_AS_WRITEFILE) { rewind($this->fp); ftruncate($this->fp,0); fwrite($this->fp,trim($this->xmlGetDoc())); flock($this->fp,LOCK_UN); fclose($this->fp); } else { return $this->objErr->throw( "Commit() can only be used when domDoc is invoked in " ."DOMDOC_AS_WRITEFILE mode" ); } return true; } /** * mass storage serialisation * * This function will dump the textual contents of the DOM document (in it's * current state to) a specified file. * * @param uri path to destination file * @return bool success or failure */ function CommitToFile($uriDestination) { $fp = fopen($uriDestination,"w+") or $this->throw("CommitToFile: could not open ".$uriDestination." for writing"); flock($fp,LOCK_EX); fwrite($fp,$this->xmlGetDoc()) or $this->throw("CommitToFile: could write to ".$uriDestination); flock($fp,LOCK_UN); fclose($fp); return true; } function ndGetOneEl($strName,$intIdx=0) { $arrNds = $this->objDoc->get_elements_by_tagname($strName); // header("Content-Type: text/plain;"); var_dump($arrNds);die(); if(isset($arrNds[$intIdx])) return $arrNds[$intIdx]; return false; } function ndAppendToRoot($strElName,$strCont = "") { $elNew = $this->objDoc->create_element($strElName); $ndNew = $this->ndRoot->append_child($elNew); $ndNew->set_content($strCont); return $ndNew; } function ndAppendToNode($ndStub,$strElName,$strCont = "") { $elNew = $this->objDoc->create_element($strElName); $ndNew = $ndStub->append_child($elNew); $ndNew->set_content($strCont); return $ndNew; } function ImportChildFrag($ndStub,$ndNew) { $ndTmp = $this->objDoc->create_element("tmp"); $ndTmp = $ndStub->append_child($ndTmp); $ndTmp->replace_node($ndNew); return $ndNew; } function ConsumeDoc($objDoc) { if(!is_object($objDoc)) $this->throw("ConsumeDoc: Non object given"); elseif(!is_object(@$objDoc->ndRoot)) $this->throw("ConsumeDoc: No root node."); else $this->ImportChildFrag($this->ndRoot,$objDoc->ndRoot); } function ConsumeFile($uri) { $objDoc = new domDoc($uri,DOMDOC_AS_READFILE); if(!is_object($objDoc)) $this->throw("ConsumeFile: $uri is not an XML document."); elseif(!is_object(@$objDoc->ndRoot)) $this->throw("ConsumeFile: No root node."); else $this->ImportChildFrag($this->ndRoot,$objDoc->ndRoot); } } ?> example include_once "class_appDoc.php"; $objApp = new appDoc();// appDoc class inherits domDoc $objDoc = new myCustomData($yadda,$yadda);//myCustomData inherits domDoc $objApp->ConsumeDoc($objDoc); ////////////// TADA!!!!!!!!!!!!!!!!!!!! echo $objApp->xmlGetDoc(); // transform or whatever... -- Terence Kearns: Web Developer University of Canberra: +61 2 6201 5516 XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|