return $this->domDoc;
 public function saveDocument()
 * save document
 {
 $this->domDoc->save($this->data['path']) ;
On implémente ces fonctions utilitaires à utilities.class.php
 public static function searchNodesByContent($pDocument, $pQueries)
 * return node matching request
 {
 $_fields = $pDocument->getElementsByTagName('fields');
 /* ceci est un exemple de mauvais code de service, 
 il ne fonctionne que pour un nombre limité de structure de crop
 c'est donc un code métier à surcharger. */
 foreach ($_fields->item(0)->childNodes as $u)
 if ($u->nodeType != XML_TEXT_NODE) 
 foreach ( $u->childNodes as $v )
 if( $v->nodeName == $pQueries['node'] 
 && ! utilities::isContent ( $pQueries['value'] 
 , $v->nodeValue ) )
 $_fields->item(0)->removeChild($u) ;
 /* OBSOLÈTE - Malheureusement, ce code ne marche pas une fois appelée par getNodes 
 for($i=0; $i<count($pNodeSet); $i++)
 $_content = $pNodeSet[$i]->childNodes ;
 // cette fonction ne descend qu'à un niveau 
 foreach($_content as $v)
 if( $v->nodeName == $pQueries['node'] 
 && ! utilities::isContent ( $pQueries['value'] 
 , $v->nodeValue ) )
 $pNodeSet[$i]->parentNode->removeChild($pNodeSet[$i]) ;
 */ 
 return $pDocument ;
 public static function searchNodesByAttribute($pDocument, $pQueries)
 * return node matching request by attribute
 {
 $_fields = $pDocument->getElementsByTagName('fields');
 foreach ($_fields->item(0)->childNodes as $u)
 if ($u->nodeType != XML_TEXT_NODE)
 if( !($u->getAttribute($pQueries['attribute']) 
 == $pQueries['value']) ) // 1:1 match
 $_fields->item(0)->removeChild($u) ;
 return $pDocument ;
On implémente la méthode getContentByData du dataManager
 public static function getContentByData($pDocument, $pData)
 * get the content from data
 {
 /* DEPRECIEE - code pour l'appel à getNodes déprécié pour searchNodes
 if($pData['node'])

if($pData['node'] != "*")
 $expr = '//'.$pData['node'].'/..' ;
 } else {
 return $pDocument ;
 } else {
 return false ;
 return utilities::searchNodes($pDocument, $pData) ;
 public static function getContentByData($pDocument, $pData)
 * get the content from data
 {
 if(@$pData['attribute'])
 return utilities::searchNodesByAttribute($pDocument, $pData) ;
 else
 return utilities::searchNodesByContent($pDocument, $pData) ; 
Un test du getContentByData nous rend nominal pour cette phase dans cette modélisation métier.
Le "refactoring" du business en services serait apprécié...
<?php
require_once "./Cms/Classes/dataManager.class.php";
require_once "./Cms/Classes/utilities.class.php";
//echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
$_manager = new dataManager();
$_manager->data['path'] = $_manager->data['root'] . "Customer1/Contents/crop1.xml"; //
// init manager
$_document = $_manager->initialize();
 // setting de valeur à récupérer
 $_manager->data['query_1'] = array("node"=>"subject","value"=>"potager");
 $_manager->data['query_2'] = array("node"=>"content","value"=>"molle2");
 // queries test
 $res = dataManager::getContentByData(
 dataManager::getContentByData($_document, $_manager->data['query_1'])
 ,$_manager->data['query_22']);
echo $res->saveXML();
<?xml version="1.0" encoding="UTF-8"?>
<crop>
 <topic>Cultiver son potager</topic>
 <scope>légumes potager soupe</scope>
 <fields>
 <field id="k_01">
 <subject>les légumes du potager</subject>
 <content>Le potager contient une terre molle. 
 Parsemé ça et là, on trouve carottes, 
 petits poids et potirons
 </content>
 </field>
 <field id="k_02">
 <subject>les légumes du test</subject>
 <content>Le potager contient une terre molle. 
 Parsemé ça et là, on Test carottes, 
 petits poids et potirons</content>
 </field>
 <field id="k_03">
 <subject>les légumes du potager</subject>
 <content>Le potager contient une terre molle2. 
 Parsemé ça et là, on trouve carottes, 
 petits poids et potirons</content>
 </field>
 </fields>
</crop>
<?xml version="1.0" encoding="UTF-8" ?> 
<crop>
 <topic>Cultiver son potager</topic> 
 <scope>légumes potager soupe</scope> 
 <fields>
 <field id="k_03">
 <subject>les légumes du potager</subject> 
 <content>Le potager contient une terre molle2. 
 Parsemé ça et là, on trouve carottes, petits poids et potirons
 </content> 
 </field>
 </fields>
</crop>
Le deuxième test de get par l'id est également concluant
 // setting de valeur à récupérer
 $_manager->data['query_1'] = array("node"=>"subject", "value"=>"potager");
 $_manager->data['query_2'] = array("attribute"=>"id", "value"=>"k_03");
 // query test
 $res = dataManager::getContentByData(
 dataManager::getContentByData($_document, $_manager->data['query_1'])
 ,$_manager->data['query_2']);
echo $res->saveXML();
Son résultat étant :
<?xml version="1.0" encoding="UTF-8" ?> 
<crop>
 <topic>Cultiver son potager</topic> 
 <scope>légumes potager soupe</scope> 
 <fields>
 <field id="k_03">
 <subject>les légumes du potager</subject> 
 <content>Le potager contient une terre molle2. 
 Parsemé ça et là, on trouve carottes, 
 petits poids et potirons
 </content> 
 </field>
 </fields>
</crop>
On implémente à utilities.class.php les méthodes :
 public static function writeContentByAttribute($pDocument, $pQueries)
 * write node content matching request by attribute
 {
 $_fields = $pDocument->getElementsByTagName('fields');
 $_flg = false ;
 foreach ($_fields->item(0)->childNodes as $u)
 if ($u->nodeType != XML_TEXT_NODE)
 if( $u->getAttribute($pQueries['attribute']) 
 == $pQueries['value'] ) // 1:1 match
 $v = $u->getElementsByTagName($pQueries['node']) ;
 $v->item(0)->nodeValue = $pQueries['replacement'] ;
 $_flg = true ;

return $_flg ;
 public static function deleteContentByContent($pDocument, $pQueries)
 * delete node matching request by attribute
 {
 $_fields = $pDocument->getElementsByTagName('fields');
 $_flg = false ;
 foreach ($_fields->item(0)->childNodes as $u)
 if ($u->nodeType != XML_TEXT_NODE)
 foreach ( $u->childNodes as $v )
 if( $v->nodeName == $pQueries['node'] 
 && utilities::isContent ( $pQueries['value'] , 
 $v->nodeValue ) )
 $_fields->item(0)->removeChild($u) ;
 $_flg = true ;
 return $_flg ;
 public static function deleteContentByAttribute($pDocument, $pQueries)
 * delete node matching request by attribute
 {
 $_fields = $pDocument->getElementsByTagName('fields');
 $_flg = false ;
 foreach ($_fields->item(0)->childNodes as $u)
 if ($u->nodeType != XML_TEXT_NODE)
 if( $u->getAttribute($pQueries['attribute']) 
 == $pQueries['value'] ) // 1:1 match
 $_fields->item(0)->removeChild($u) ;
 $_flg = true ;
 return $_flg ;

et à la classe dataManager.class.php
 public function setContentByData($pDocument,$pData)
 * set the content to data
 {
 if(@$pData['attribute'])
 utilities::writeContentByAttribute($pDocument, $pData) ;
 else
 utilities::writeContentByContent($pDocument, $pData) ;
 $this->saveDocument();
Le test suivant permet de valider la phase d'écriture :
 // setting de valeur à récupérer
 $_manager->data['query_1'] = array("attribute"=>"id", "value"=>"k_03","node"=>"subject",
 "replacement"=>"this is the new subject");
 // query test
 $_manager->setContentByData($_document, $_manager->data['query_1']);
avec le resultat
 <field id="k_03">
 <subject>this is the new subject</subject>
 <content>Le potager contient une terre molle2. 
 Parsemé ça et là, on trouve carottes, 
 petits poids et potirons
 </content>
 </field>
[2] Gestion des utilisateurs.
La gestion des utilisateurs suivant le modèle ne demande que l'extraction de la ligne utilisateur pour recueillir ses infos.
Dans la classe utilities.class.php on rajoute ces deux méthodes :
 public static function getAttributesContents($pNode)
 * retourne les attributs dans un tableau
 {
 foreach ($pNode->attributes as $attrName => $attrNode)
 $_tab[$attrName] = $attrNode->value ;