| Server IP : 54.36.91.62 / Your IP : 216.73.217.112 Web Server : Apache System : Linux webm013.cluster127.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : coopiak ( 151928) PHP Version : 8.3.23 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/coopiak/amisdesseniors-fr/previous-website/06/libraries/CBLib/CBLib/Xml/ |
Upload File : |
<?php
/**
* CBLib, Community Builder Library(TM)
* @version $Id: 10.06.13 15:47 $
* @package CBLib\Core
* @copyright (C) 2004-2023 www.joomlapolis.com / Lightning MultiCom SA - and its licensors, all rights reserved
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU/GPL version 2
*/
namespace CBLib\Xml;
defined('CBLIB') or die();
/**
* SimpleXML Element extended for CB.
*
*/
class SimpleXMLElement extends \SimpleXMLElement implements \Countable
{
/**
* This function is only here to satisfy a phplint bug giving false warnings:
*
* Finds children of given node
*
* @param string $ns [optional] An XML namespace.
* @param bool $is_prefix [optional] If true, ns will be regarded as a prefix. If false, ns will be regarded as a namespace URL.
* @return SimpleXMLElement[] a SimpleXMLElement element, whether the node has children or not.
*/
#[\ReturnTypeWillChange]
public function children( $ns = null, $is_prefix = false )
{
return parent::children( $ns, $is_prefix );
}
/**
* Get the name of the element (same as getName() for compatibility reasons).
* @deprecated 2.0 : Use ->getName() instead.
*
* @return string The getName of the element
*/
public function name( ) {
return $this->getName();
}
/**
* Get the an attribute or all attributes of the element
*
* @param string $attribute The name of the attribute if only one attribute is fetched
* @param bool $is_prefix [optional] defaults to False
* @return array|bool|string string If an attribute is given will return the attribute if it exist.
* boolean Null if attribute is given but doesn't exist
* array If no attribute is given will return the complete attributes array
*/
#[\ReturnTypeWillChange]
public function attributes( $attribute = null, $is_prefix = false )
{
if( isset( $attribute ) ) {
return ( isset( $this[$attribute]) ? (string) $this[$attribute] : null );
}
$array = array();
foreach ( parent::attributes() as $k => $v ) {
$array[$k] = (string) $v;
}
return $array;
}
/**
* Get the data of the element
*
* @return string
*/
public function data( ) {
return (string) $this;
}
/**
* Adds an attribute to the element, override if it already exists
*
* @param string $name Name of attribute
* @param null $value Value of attribute
* @param null $ns Name-space
* @return void
*/
#[\ReturnTypeWillChange]
public function addAttribute( $name, $value = null, $ns = null )
{
$this[$name] = $value;
}
/**
* Get an element in the document by / separated path
* or FALSE
*
* @param string $path The / separated path to the element
* @return SimpleXMLElement|null Element or NULL
*/
public function getElementByPathOrNull( $path )
{
$elem = $this->getElementByPath( $path );
if ( $elem === false ) {
$elem = null;
}
return $elem;
}
/**
* Get an element in the document by / separated path
* or FALSE
*
* @param string $path The / separated path to the element
* @return SimpleXMLElement|bool Element or FALSE
*/
public function & getElementByPath( $path ) {
$parts = explode( '/', trim($path, '/') );
$tmp = $this;
$found = false;
foreach ( $parts as $node ) {
$found = false;
foreach ( $tmp->children() as $child ) {
/** @var SimpleXMLElement $child */
if ( $child->getName() == $node ) {
$tmp = $child;
$found = true;
break;
}
}
if ( ! $found ) {
break;
}
}
if ( $found ) {
return $tmp;
} else {
$false = false;
return $false;
}
}
/**
* Adds a direct child to the element
*
* @param string $name Name tag of element
* @param string $value Text value of element
* @param string $nameSpace [optional] Namespace
* @param array $attrs [optional] Keyed Attributes
* @return SimpleXMLElement The created child
*/
public function & addChildWithAttr( $name, $value, $nameSpace = null, $attrs = null ) {
if ( $attrs === null ) {
$attrs = array();
}
$child = parent::addChild( $name, htmlspecialchars( (string) $value ), $nameSpace );
foreach ( $attrs as $k => $v ) {
$child->addAttribute( $k, $v );
}
return $child;
}
/**
* Removes a child node from $this
* CB 2.0 Experimental API (subject to change/remove)
*
* @param SimpleXMLElement $node The child to remove
*/
public function removeChild( $node ) {
$domNode = dom_import_simplexml( $this );
$childDomNode = dom_import_simplexml( $node );
$domNode->removeChild( $childDomNode );
}
/**
* Appends a child node to $this
* CB 2.0 Experimental API (subject to change/remove)
*
* @param SimpleXMLElement $node The child to append
*/
public function appendChild( $node ) {
$domNode = dom_import_simplexml( $this );
$childDomNode = dom_import_simplexml( $node );
$domNode->appendChild( $childDomNode );
}
/**
* Replace $this by $replacementXmlNode and its children in the XML tree, and extract $this from the tree
*
* @since 1.2.4
*
* @param SimpleXMLElement $replacementXmlNode New XML node to replace $this
* @param callback $callBack To check/transform data or attributes of a node: $destinationData = function ( string|array $sourceData, SimpleXMLElement $sourceNode, SimpleXMLElement $destinationParentNode );
* @param bool $clone True: always clone $replacementXmlNode before replacing; False: only clone if parents are same
* @return SimpleXMLElement $this : Old extracted $this XML node
*/
public function & replaceNodeAndChildren( &$replacementXmlNode, $callBack = null, $clone = false ) {
$domNode = dom_import_simplexml( $this );
$otherDomReplacement = dom_import_simplexml( $replacementXmlNode );
/** @var \DOMElement $domReplacement */
$domReplacement = $domNode->ownerDocument->importNode( $otherDomReplacement );
if ( $clone || ( $domReplacement->parentNode === $domNode ) ) {
// We're trying to replace a node with its own child node, which causes a reference error so make a clone first
$domReplacement = $domReplacement->cloneNode( true );
}
$domNode->parentNode->replaceChild( $domReplacement, $domNode );
$this->_domCopyChildrenCallbackonNode( $domReplacement, $replacementXmlNode, $callBack );
return $this;
}
/**
* Inserts $xmlNodeToInsert (and its children) as sibbling BEFORE $this in the XML tree, and returns the new XML node
*
* @since 1.2.4
*
* @param SimpleXMLElement $xmlNodeToInsert New XML node to insert BEFORE $this
* @param callback $callBack To check/transform data or attributes of a node: $destinationData = function ( string|array $sourceData, SimpleXMLElement $sourceNode, SimpleXMLElement $destinationParentNode );
* @param bool $clone True: always clone $replacementXmlNode before replacing; False: only clone if parents are same
* @return SimpleXMLElement New node
*/
public function & insertNodeAndChildrenBefore( &$xmlNodeToInsert, $callBack = null, $clone = false ) {
$domNode = dom_import_simplexml( $this );
$otherDomNodeToInsert = dom_import_simplexml( $xmlNodeToInsert );
$domNodeToInsert = $domNode->ownerDocument->importNode( $otherDomNodeToInsert );
if ( $clone || ( $domNodeToInsert->parentNode === $domNode ) ) {
// We're trying to insert before its own parent, which causes a reference error so make a clone first
$domNodeToInsert = $domNodeToInsert->cloneNode( true );
}
/** @var \DOMElement $newNode */
$newNode = $domNode->parentNode->insertBefore( $domNodeToInsert, $domNode );
$sibbling = $this->_domCopyChildrenCallbackonNode( $newNode, $xmlNodeToInsert, $callBack );
return $sibbling;
}
/**
* Inserts $xmlNodeToInsert (and its children) as sibbling AFTER $this in the XML tree, and returns the new XML node
*
* @since 1.2.4
*
* @param SimpleXMLElement $xmlNodeToInsert New XML node to insert AFTER $this
* @param callback $callBack To check/transform data or attributes of a node: $destinationData = function ( string|array $sourceData, SimpleXMLElement $sourceNode, SimpleXMLElement $destinationParentNode );
* @param bool $clone True: always clone $replacementXmlNode before replacing; False: only clone if parents are same
* @return SimpleXMLElement New node
*/
public function & insertNodeAndChildrenAfter( &$xmlNodeToInsert, $callBack = null, $clone = false ) {
$domNode = dom_import_simplexml( $this );
$otherDomNodeToInsert = dom_import_simplexml( $xmlNodeToInsert );
$domNodeToInsert = $domNode->ownerDocument->importNode( $otherDomNodeToInsert );
if ( $clone || ( $domNodeToInsert->parentNode === $domNode ) ) {
// We're trying to insert after its own parent, which causes a reference error so make a clone first
$domNodeToInsert = $domNodeToInsert->cloneNode( true );
}
if( $domNode->nextSibling ) {
/** @var \DOMElement $newNode */
$newNode = $domNode->parentNode->insertBefore( $domNodeToInsert, $domNode->nextSibling );
$sibling = $this->_domCopyChildrenCallbackonNode( $newNode, $xmlNodeToInsert, $callBack );
} else {
// $newNode = $domNode->parentNode->appendNode( $domNodeToInsert, $domNode->nextSibling );
/** @var SimpleXMLElement[] $parent SimpleXMLElement way which adds descendants too */
$parent = $this->xpath( '..' );
$sibling = $parent[0]->addChildWithDescendants( $xmlNodeToInsert, $callBack );
}
return $sibling;
}
/**
* Protected internal function that handles missing DOM functionality:
* $callBack to the copied attributes and data, as well as copying of children.
*
* @since 1.2.4
*
* @param \DOMElement $newNode New DOM (incomplete) node just inserted/replaced
* @param SimpleXMLElement $xmlSourceNode Original XML node that got copied into DOM
* @param callback $callBack To check/transform data or attributes of a node: $destinationData = function ( string|array $sourceData, SimpleXMLElement $sourceNode, SimpleXMLElement $destinationParentNode );
* @return SimpleXMLElement New XML node
*/
protected function & _domCopyChildrenCallbackonNode( &$newNode, $xmlSourceNode, $callBack ) {
/** @var SimpleXMLElement $newNodeXML */
$newNodeXML = simplexml_import_dom( $newNode, get_class( $this ) );
if ( $callBack === null ) {
$newNode->nodeValue = $xmlSourceNode->data(); //FIXME: side-effect: this removes children from $xmlSourceNode IF both are in the same ownerDocument, but removing that line makes copying children infinite looping below
} else {
$newNode->nodeValue = call_user_func_array( $callBack, array( $xmlSourceNode->data(), $xmlSourceNode, $newNodeXML ) );
$copiedAttributes = $newNode->attributes;
foreach ( $copiedAttributes as $k => $v ) {
$newNode->removeAttribute( $k );
}
// the new set of $attributes can be different from old one, thus we needed to remove old set (copied in PHP 5.3 only) first, then copy new:
$attributes = call_user_func_array( $callBack, array( $xmlSourceNode->attributes(), $xmlSourceNode, $newNodeXML ) );
foreach ( $attributes as $k => $v ) {
$newNode->setAttribute( $k, $v );
}
}
foreach ($xmlSourceNode->children() as $child ) {
$newNodeXML->addChildWithDescendants( $child, $callBack );
}
return $newNodeXML;
}
/**
* Get the first child element in matching all the attributes $attributes
*
* @param string $name The name tag of the element searched
* @param array $attributes array of attribute => value which must match also
* @return SimpleXMLElement|bool Child or false if no child matches
*/
public function &getChildByNameAttributes( $name, $attributes = null ) {
if ( $attributes === null ) {
$attributes = array();
}
foreach ( $this->children() as $child ) {
/** @var SimpleXMLElement $child */
if ( $child->getName() == $name ) {
$found = true;
foreach ( $attributes as $atr => $val ) {
if ( $child->attributes( $atr ) != $val ) {
$found = false;
break;
}
}
if ( $found ) {
return $child;
}
}
}
$false = false;
return $false;
}
/**
* Get the first child element in matching the attribute
*
* @param string $name The name tag of the element searched
* @param string $attribute Attribute name to check
* @param string $value Attribute value which must also match
* @return SimpleXMLElement|bool Child or false if no child matches
*/
public function &getChildByNameAttr( $name, $attribute, $value = null ) {
foreach ( $this->children() as $child ) {
/** @var SimpleXMLElement $child */
if ( $child->getName() == $name ) {
if ( $child->attributes( $attribute ) == $value ) {
return $child;
}
}
}
$false = false;
return $false;
}
/**
* Get the first child or childs' child (recursing) element in matching the attiribute
*
* @param string $name The name tag of the element searched
* @param string $attribute Attribute name to check
* @param string $value Attribute value which must also match
* @return SimpleXMLElement|bool Child or false if no child matches
*/
public function &getAnyChildByNameAttr( $name, $attribute, $value = null ) {
$children = $this->children(); // this is needed due to a bug in PHP 4.4.2 where you can have only 1 iterator per array reference, so doing second iteration on same array within first iteration kills this.
foreach ( $children as $child ) {
/** @var SimpleXMLElement $child */
if ( $child->getName() == $name ) {
if ( $child->attributes( $attribute ) == $value ) {
return $child;
}
}
if ( count( $child->children() ) > 0 ) {
$grandchild = $child->getAnyChildByNameAttr( $name, $attribute, $value ); // recurse
if ( $grandchild ) {
return $grandchild;
}
}
}
$false = false;
return $false;
}
/**
* Appends (copies) a child $source and all its descendants to $this node
*
* @param SimpleXMLElement|\SimpleXMLElement $source
* @param callback $callBack to check/transform data or attributes of a node: $destinationData = function ( string|array $sourceData, SimpleXMLElement $sourceNode, SimpleXMLElement $destinationParentNode );
* @return SimpleXMLElement
*/
public function & addChildWithDescendants( &$source, $callBack = null ) {
if ( $callBack === null ) {
$child = $this->addChildWithAttr( $source->getName(), $source->data(), null, $source->attributes() );
} else {
$child = $this->addChildWithAttr( $source->getName(), call_user_func_array( $callBack, array( $source->data(), $source, $this ) ), null, call_user_func_array( $callBack, array( $source->attributes(), $source, $this ) ) );
}
foreach ( $source->children() as $sourceChild ) {
$child->addChildWithDescendants( $sourceChild, $callBack );
}
return $child;
}
}