Файл: IPBMafia.ru_IPB_3.4.6_Final_Rus _Nulled/board/upload/ips_kernel/classXML.php
Строк: 533
<?php
/**
* <pre>
* Invision Power Services
* IP.Board v3.4.6
* XML Handler: Rewritten for PHP5
* By Matt Mecham
* Last Updated: $Date: 2012-07-27 11:43:25 -0400 (Fri, 27 Jul 2012) $
* </pre>
*
* @author $Author: mark $
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
* @license http://www.invisionpower.com/company/standards.php#license
* @package IP.Board
* @subpackage Kernel
* @link http://www.invisionpower.com
* @since 25th February 2004
* @version $Revision: 11149 $
*
*
* Example Usage:
* <code>
* <productlist name="myname" version="1.0">
* <productgroup name="thisgroup">
* <product id="1.0">
* <description>This is a descrption</description>
* <title>Baked Beans</title>
* <room store="1">103</room>
* </product>
* <product id="2.0">
* <description>This is another descrption</description>
* <title>Green Beans</title>
* <room store="2">104</room>
* </product>
* </productgroup>
* </productlist>
*
* Creating...
* $xml = new classXML( 'utf-8' );
* $xml->newXMLDocument();
*
* /* Create a root element * /
* $xml->addElement( 'productlist', '', array( 'name' => 'myname', 'version' => '1.0' ) );
* /* Add a child.... * /
* $xml->addElement( 'productgroup', 'productlist', array( 'name' => 'thisgroup' ) );
* $xml->addElementAsRecord( 'productgroup',
* array( 'product', array( 'id' => '1.0' ) ),
* array( 'description' => array( 'This is a description' ),
* 'title' => array( 'Baked Beans' ),
* 'room' => array( '103', array( 'store' => 1 ) )
* )
* );
* $xml->addElementAsRecord( 'productgroup',
* array( 'product', array( 'id' => '2.0' ) ),
* array( 'description' => array( 'This is another description' ),
* 'title' => array( 'Green Beans' ),
* 'room' => array( '104', array( 'store' => 2 ) )
* )
* );
*
* $xmlData = $xml->fetchDocument();
*
* /*Convering XML into an array * /
* $xml->loadXML( $xmlData );
*
* /* Grabbing specific data values from all 'products'... * /
* foreach( $xml->fetchElements('product') as $products )
* {
* print $xml->fetchItem( $products, 'title' ) . "\";
* }
*
* /* Prints... * /
* Baked Beans
* Green Beans
*
* /* Print all array data - auto converts XML_TEXT_NODE and XML_CDATA_SECTION_NODE into #alltext for brevity * /
* print_r( $xml->fetchXMLAsArray() );
*
* /* Prints * /
* Array
* (
* [productlist] => Array
* (
* [@attributes] => Array
* (
* [name] => myname
* [version] => 1.0
* )
* [productgroup] => Array
* (
* [@attributes] => Array
* (
* [name] => thisgroup
* )
* [product] => Array
* (
* [0] => Array
* (
* [@attributes] => Array
* (
* [id] => 1.0
* )
* [description] => Array
* (
* [#alltext] => This is a description
* )
* [title] => Array
* (
* [#alltext] => Baked Beans
* )
* [room] => Array
* (
* [@attributes] => Array
* (
* [store] => 1.0
* )
* [#alltext] => 103
* )
* )
* [1] => Array
* (
* [@attributes] => Array
* (
* [id] => 2.0
* )
* [description] => Array
* (
* [#alltext] => This is another description
* )
* [title] => Array
* (
* [#alltext] => Green Beans
* )
* [room] => Array
* (
* [@attributes] => Array
* (
* [store] => 1.0
* )
* [#alltext] => 104
* )
* )
* )
* )
* )
* )
*
* </code>
*
*/
class classXML
{
/**
* Document character set
*
* @var string
*/
protected $_docCharSet = 'utf-8';
/**
* Current document object
*
* @var object
*/
protected $_dom;
/**
* Array of DOM objects
*
* @var array
*/
protected $_domObjects = array();
/**
* XML array
*
* @var array
*/
protected $_xmlArray = array();
/**
* Conversion class
*
* @var object
*/
protected static $classConvertCharset;
/**
* Constructor
*
* @param string Character Set
* @return @e void
*/
public function __construct( $charSet )
{
$this->_docCharSet = strtolower( $charSet );
}
/**
* Create new document
*
* @return @e void
*/
public function newXMLDocument()
{
$this->_dom = new DOMDocument( '1.0', 'utf-8' );
}
/**
* Fetch the document
*
* @return @e string
*/
public function fetchDocument()
{
$this->_dom->formatOutput = TRUE;
return $this->_dom->saveXML();
}
/**
* Add element into the document
*
* @param string Name of tag to create
* @param string [Name of parent tag (optional)]
* @param array [Attributes]
* @param string [Namespace URI]
* @return @e void
*/
public function addElement( $tag, $parentTag='', $attributes=array(), $namespaceUri='' )
{
$this->_domObjects[ $tag ] = $this->_node( $parentTag )->appendChild( new DOMElement( $tag, '', $namespaceUri ) );
$this->addAttributes( $tag, $attributes );
}
/**
* Add element into the document as a record row
* You can pass $tag as either a string or an array
*
* $xml->addElementAsRecord( 'parentTag', 'myTag', $data );
* $xml->addElementAsRecord( 'parentTag', array( 'myTag', array( 'attr' => 'value' ) ), $data );
*
* @param string Name of parent tag
* @param mixed Tag wrapper
* @param array Array of data to add
* @param string [Namespace URI]
* @return @e void
*/
public function addElementAsRecord( $parentTag, $tag, $data, $namespaceUri='' )
{
/* A little set up if you please... */
$_tag = $tag;
$_tag_attr = array();
if ( is_array( $tag ) )
{
$_tag = $tag[0];
$_tag_attr = $tag[1];
}
$record = $this->_node( $parentTag )->appendChild( new DOMElement( $_tag, ( is_array( $data ) ? NULL : $data ), $namespaceUri ) );
if ( is_array( $_tag_attr ) AND count( $_tag_attr ) )
{
foreach( $_tag_attr as $k => $v )
{
$record->appendChild( new DOMAttr( $k, $v ) );
}
}
/* Now to add the data */
if ( is_array( $data ) AND count( $data ) )
{
foreach( $data as $rowTag => $rowData )
{
/* You can pass an array.. or not if you don't need attributes */
if ( ! is_array( $rowData ) )
{
$rowData = array( 0 => $rowData );
}
if ( preg_match( "/['"[]<>&]/", $rowData[0] ) )
{
$_child = $record->appendChild( new DOMElement( $rowTag ) );
$_child->appendChild( new DOMCDATASection( $this->_inputToXml( $rowData[0] ) ) );
}
else
{
$_child = $record->appendChild( new DOMElement( $rowTag, $this->_inputToXml( $rowData[0] ) ) );
}
if ( $rowData[1] )
{
foreach( $rowData[1] as $_k => $_v )
{
$_child->appendChild( new DOMAttr( $_k, $_v ) );
}
}
unset( $_child );
}
}
}
/**
* Add attributes to a node
*
* @param string Name of tag
* @param array Array of attributes in key => value format
* @return @e void
*/
public function addAttributes( $tag, $data )
{
if ( is_array( $data ) AND count( $data ) )
{
foreach( $data as $k => $v )
{
$this->_node( $tag )->appendChild( new DOMAttr( $k, $v ) );
}
}
}
/**
* Load a document from a file
*
* @param string File name
* @return @e void
*/
public function load( $filename )
{
$this->_dom = new DOMDocument;
$this->_dom->load( $filename );
}
/**
* Load a document from a string
*
* @param string XML Data
* @return @e bool
*/
public function loadXML( $xmlData )
{
$this->_dom = new DOMDocument;
if( defined('LIBXML_PARSEHUGE') )
{
return @$this->_dom->loadXML( $xmlData, LIBXML_PARSEHUGE );
}
else
{
return @$this->_dom->loadXML( $xmlData );
}
}
/**
* Wrapper function: Fetch elements based on tag name
*
* @param string Tag Name to fetch from the DOM tree
* @param object Node to start from
* @return @e array
*/
public function fetchElements( $tag, $node=null )
{
$start = $node ? $node : $this->_dom;
$_elements = $start->getElementsByTagName( $tag );
return ( $_elements->length ) ? $_elements : array();
}
/**
* Wrapper function: Fetch all items within a parent tag
*
* @param object DOM object as returned from getElementsByTagName
* @param array array of node names to skip
* @return @e array
*/
public function fetchElementsFromRecord( $dom, $skip=array() )
{
$array = array();
foreach( $dom->childNodes as $node )
{
if ( $node->nodeType == XML_ELEMENT_NODE )
{
if ( is_array( $skip ) )
{
if ( in_array( $node->nodeName, $skip ) )
{
continue;
}
}
$array[ $node->nodeName ] = $this->_xmlToOutput( $node->nodeValue );
}
}
return $array;
}
/**
* Wrapper function: Fetch items from an element node
*
* @param object DOM object as returned from getElementsByTagName
* @param string [Optional: Tag name if the DOM is a parent]
* @return @e string
*/
public function fetchItem( $dom, $tag='' )
{
if ( $tag )
{
$_child = $dom->getElementsByTagName( $tag );
return $this->_xmlToOutput( $_child->item(0)->firstChild->nodeValue );
}
else
{
return $this->_xmlToOutput( $dom->nodeValue );
}
}
/**
* Wrapper function: Fetch attributes from an element node's item
*
* @param object DOM object as returned from getElementsByTagName
* @param string Attribute name required...
* @param string [Optional: Tag name if the DOM is a parent]
* @return @e string
*/
public function fetchAttribute( $dom, $attribute, $tag='' )
{
if ( $tag )
{
$_child = $dom->getElementsByTagName( $tag );
return $_child->item(0)->getAttribute( $attribute );
}
else
{
return $dom->getAttribute( $attribute );
}
}
/**
* Wrapper function: Fetch all attributes from an element node's item
*
* @param object DOM object as returned from getElementsByTagName
* @param string Tag name to fetch attribute from
* @return @e array
*/
public function fetchAttributesAsArray( $dom, $tag )
{
$attrs = array();
$_child = $dom->getElementsByTagName( $tag );
$attributes = $_child->item(0)->attributes;
foreach( $attributes as $val )
{
$attrs[ $val->nodeName ] = $val->nodeValue;
}
return $attrs;
}
/**
* Fetch entire DOM tree into a single array
*
* @return @e array
*/
public function fetchXMLAsArray()
{
return $this->_fetchXMLAsArray( $this->_dom );
}
/**
* Internal function to recurse through and collect nodes and data
*
* @param DOM object Node element
* @return @e array
*/
protected function _fetchXMLAsArray( $node )
{
$_xmlArray = array();
if ( $node->nodeType == XML_TEXT_NODE )
{
$_xmlArray = $this->_xmlToOutput( $node->nodeValue );
}
else if ( $node->nodeType == XML_CDATA_SECTION_NODE )
{
$_xmlArray = $this->_xmlToOutput( $node->nodeValue );
}
else
{
if ( $node->hasAttributes() )
{
$attributes = $node->attributes;
if ( ! is_null( $attributes ) )
{
foreach( $attributes as $index => $attr )
{
$_xmlArray['@attributes'][ $attr->name ] = $attr->value;
}
}
}
if ( $node->hasChildNodes() )
{
$children = $node->childNodes;
$occurance = array();
foreach( $children as $nc)
{
if ( $nc->nodeName != '#text' AND $nc->nodeName != '#cdata-section' )
{
$occurance[ $nc->nodeName ] = isset($occurance[ $nc->nodeName ]) ? $occurance[ $nc->nodeName ] + 1 : 1;
}
}
for( $i = 0 ; $i < $children->length ; $i++ )
{
$child = $children->item( $i );
$_name = $child->nodeName;
if ( $child->nodeName == '#text' OR $child->nodeName == '#cdata-section' )
{
$_name = '#alltext';
}
if ( isset($occurance[ $child->nodeName ]) AND $occurance[ $child->nodeName ] > 1 )
{
$_xmlArray[ $_name ][] = $this->_fetchXMLAsArray( $child );
}
else
{
$_xmlArray[ $_name ] = $this->_fetchXMLAsArray( $child );
}
}
}
}
return $_xmlArray;
}
/**
* Encode CDATA XML attribute (Make safe for transport)
*
* @param string Raw data
* @return @e string
*/
protected function _xmlConvertSafecdata( $v )
{
$v = str_replace( "<![CDATA[", "<!#^#|CDATA|", $v );
$v = str_replace( "]]>" , "|#^#]>" , $v );
return $v;
}
/**
* Decode CDATA XML attribute (Make safe for transport)
*
* @param string Raw data
* @return @e string
*/
protected function _xmlUnconvertSafecdata( $v )
{
$v = str_replace( "<!#^#|CDATA|", "<![CDATA[", $v );
$v = str_replace( "|#^#]>" , "]]>" , $v );
return $v;
}
/**
* Return a tag object
*
* @param string Name of tag
* @return @e object
*/
protected function _node( $tag )
{
if ( isset($this->_domObjects[ $tag ]) )
{
return $this->_domObjects[ $tag ];
}
else
{
return $this->_dom;
}
}
/**
* Convert from native to UTF-8 for saving XML
*
* @param string Input Text
* @return @e string
*/
protected function _inputToXml( $text )
{
/* Do we need to make safe on CDATA? */
if ( preg_match( "/['"[]<>&]/", $text ) )
{
$text = $this->_xmlConvertSafecdata( $text );
}
/* Using UTF-8 */
if ( $this->_docCharSet == 'utf-8' )
{
return $text;
}
/* Are we using the most common ISO-8559-1... */
else if ( $this->_docCharSet == 'iso-8859-1' )
{
return utf8_encode( $text );
}
else
{
return $this->_convertCharsets( $text, $this->_docCharSet, 'utf-8' );
}
}
/**
* Convert from UTF-8 to native for saving XML
*
* @param string Input Text
* @return @e string
*/
protected function _xmlToOutput( $text )
{
/* Unconvert cdata */
$text = $this->_xmlUnconvertSafecdata( $text );
/* Using UTF-8 */
if ( $this->_docCharSet == 'utf-8' )
{
return $text;
}
/* Are we using the most common ISO-8559-1... */
else if ( $this->_docCharSet == 'iso-8859-1' )
{
return utf8_decode( $text );
}
else
{
return $this->_convertCharsets( $text, 'utf-8', $this->_docCharSet );
}
}
/**
* Convert a string between charsets. XML will always be UTF-8
*
* @param string Input String
* @param string Current char set
* @param string Destination char set
* @return @e string
* @todo [Future] If an error is set in classConvertCharset, show it or log it somehow
*/
protected function _convertCharsets( $text, $original_cset, $destination_cset="UTF-8" )
{
$original_cset = strtolower($original_cset);
$destination_cset = strtolower( $destination_cset );
$t = $text;
//-----------------------------------------
// Not the same?
//-----------------------------------------
if ( $destination_cset == $original_cset )
{
return $t;
}
if ( ! is_object( self::$classConvertCharset ) )
{
require_once( dirname(__FILE__) . '/classConvertCharset.php' );/*noLibHook*/
self::$classConvertCharset = new classConvertCharset();
//-----------------------------------------
// Ok, mb functions only support limited number
// of charsets, so if mb functions are enabled
// but using e.g. windows-1250, no conversion
// ends up happening. Let's force internal.
//-----------------------------------------
//if ( function_exists( 'mb_convert_encoding' ) )
//{
// self::$classConvertCharset->method = 'mb';
//}
//else if ( function_exists( 'iconv' ) )
//{
// self::$classConvertCharset->method = 'iconv';
//}
//else if ( function_exists( 'recode_string' ) )
//{
// self::$classConvertCharset->method = 'recode';
//}
//else
//{
self::$classConvertCharset->method = 'internal';
//}
}
$text = self::$classConvertCharset->convertEncoding( $text, $original_cset, $destination_cset );
return $text ? $text : $t;
}
}