[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

Subject: Re: Editing XML dynamically and using two input XML files
From: Terence Kearns <terencek@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 30 May 2003 17:48:59 +1000
could not open xml input
thei wrote:
Hello,

I have two questions.

Firstly, I want to be able to take two XML files as input, and transform
them into one XML (actually XHTML) output file. I'm using XSLT
(specifically Sablotron under PHP/Apache/Linux). Is this possible?

Secondly, I wish to be able to grab a specific section of an XML file,
load it into a web-form, allow it to be edited, and then save it back to
the original XML file in the same location. It has to be UTF-8
throughout.


<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


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.