Método que convierte el XML a un arreglo
@author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
@version 2016-06-11
760179
public function toArray(\DOMElement $dom = null, array &$array = null, $arregloNodos = false)
    {
        // determinar valores de parámetros
        if (!$dom)
            $dom = $this->documentElement;
        if (!$dom)
            return false;
        if ($array===null)
            $array = [$dom->tagName => null];
        // agregar atributos del nodo
        if ($dom->hasAttributes()) {
            $array[$dom->tagName]['@attributes'] = [];
            foreach ($dom->attributes as $attribute) {
                $array[$dom->tagName]['@attributes'][$attribute->name] = $attribute->value;
            }
        }
        // agregar nodos hijos
        if ($dom->hasChildNodes()) {
            foreach($dom->childNodes as $child) {
                if ($child instanceof \DOMText) {
                    $textContent = trim($child->textContent);
                    if ($textContent!="") {
                        if ($dom->childNodes->length==1 and empty($array[$dom->tagName])) {
                            $array[$dom->tagName] = $textContent;
                        } else
                            $array[$dom->tagName]['@value'] = $textContent;
                    }
                }
                else if ($child instanceof \DOMElement) {
                    $nodos_gemelos = $this->countTwins($dom, $child->tagName);
                    if ($nodos_gemelos==1) {
                        if ($arregloNodos)
                            $this->toArray($child, $array);
                        else
                            $this->toArray($child, $array[$dom->tagName]);
                    }
                    // crear arreglo con nodos hijos que tienen el mismo nombre de tag
                    else {
                        if (!isset($array[$dom->tagName][$child->tagName]))
                            $array[$dom->tagName][$child->tagName] = [];
                        $siguiente = count($array[$dom->tagName][$child->tagName]);
                        $array[$dom->tagName][$child->tagName][$siguiente] = [];
                        $this->toArray($child, $array[$dom->tagName][$child->tagName][$siguiente], true);
                    }
                }
            }
        }
        // entregar arreglo
        return $array;
    }
608771
public function to_xml_start(){
		$str="<update ";
		$str .= 'status="'.$this->data['action_table_type'].'" ';
		$str .= 'id="'.$this->data['dataId'].'" ';
		$str .= 'parent="'.$this->get_parent_id().'"';
		$str .= '>';
		$str .= $this->child->to_xml_start();
		return $str;
	}
413767
public function loadAsXML()
    {
        $this->checkFileExists();
        $xml = new \DomDocument ();
        libxml_use_internal_errors(true);
        $result = $xml->load($this->absoluteFileName);
        if ($result) {
            return $xml;
        }
        $messageObject = ArrayUtil::getFromArray(libxml_get_errors(), 0);
        $libXMLMessage = ObjectUtil::getFromObject($messageObject, "message");
        $message = sprintf(self::EXCEPTION_INVALID_XML, $this->absoluteFileName, $libXMLMessage);
        $e = new \Exception(libxml_get_errors()[0]->message);
        libxml_clear_errors();
        throw $e;
    }
1124355
private function propertiesToXml() {
        $properties = array();

        foreach (self::$properties[get_class($this)] as $name => $info) {
            if($info['attribute']) {
                continue;
            }

            if (!array_key_exists($name, $this->values)) {
                continue;
            }

            $value = $this->values[$name];

            if(!array_key_exists('elementName', $info) && !array_key_exists('attributeName', $info)) {
                $properties[] = self::encodeValueXml($value);
            }
            else {
                if ($info['unbound']) {
                    foreach($value as $property) {
                        $properties[] = self::propertyToXml($info['elementName'], $property);
                    }
                } else {
                    $properties[] = self::propertyToXml($info['elementName'], $value);
                }
            }
        }

        return join('', $properties);
    }
1340311
private function xml() {
    	$document = new DOMDocument('1.0', 'UTF-8');
    	$document->appendChild($this->buildElement($this, $document));
    	return $document;
    }
118392
function to_xml(){
        if ($this->skip) return "";

        $obj = array();
        $obj['id'] = $this->get_id();
        $obj['start_date'] = $this->data[$this->config->text[0]["name"]];
        $obj[$this->config->text[1]["name"]] = $this->data[$this->config->text[1]["name"]];
        $obj['text'] = $this->data[$this->config->text[2]["name"]];
        for ($i=3; $i<sizeof($this->config->text); $i++){
            $extra = $this->config->text[$i]["name"];
            $obj[$extra]=$this->data[$extra];
        }
        
        if ($this->userdata !== false)
            foreach ($this->userdata as $key => $value)
                $obj[$key]=$value;

        return $obj;
    }
270386
public function loadXML($xml_data)
    {
        if (!parent::loadXML($xml_data)) {
            return false;
        }
        $tagName = $this->xml->documentElement->tagName;
        if ($tagName=='DTE') {
            $this->xml = null;
            $this->xml_data = null;
            $this->arreglo = null;
            $Dte = new Dte($xml_data, false);
            $this->agregar($Dte);
            $this->setCaratula([
                'RutEnvia' => $Dte->getEmisor(),
                'RutReceptor' => $Dte->getReceptor(),
                'FchResol' => date('Y-m-d'),
                'NroResol' => ($Dte->getCertificacion()?'0':'').'9999',
            ]);
            if (!parent::loadXML($this->generar())) {
                return false;
            }
            $tagName = $this->xml->documentElement->tagName;
        }
        if ($tagName=='EnvioDTE') {
            $this->tipo = 0;
            return $this->xml;
        }
        if ($tagName=='EnvioBOLETA') {
            $this->tipo = 1;
            return $this->xml;
        }
        return false;
    }
129033
public function getXmlLang()
	{
		// Take and work on a copy of the node so it can be manipulated
		$node = $this->domNode;

		while ( ! $node instanceof \DOMDocument )
		{
			if ( $node->hasAttributes() )
			{
				foreach ( $node->attributes as $name => $attrNode )
				{
					// This should return the lang attribute of the node if there is one.
					if ( $name != "lang" || $attrNode->localName != "lang" || $attrNode->namespaceURI != XmlReservedNs::xml ) continue;
					return $attrNode->nodeValue;
				}
			}

			// If not, check the parent recursively
			$node = $node->parentNode;
		}

		return "";
	}
762871
public function xml()
    {
        if (empty($this->_result)) {
            return $this->xml->getSimpleXmlElement();
        }
        $hideRaids = array();
        if (defined('PSI_PLUGIN_RAID_HIDE_DEVICES') && is_string(PSI_PLUGIN_RAID_HIDE_DEVICES)) {
            if (preg_match(ARRAY_EXP, PSI_PLUGIN_RAID_HIDE_DEVICES)) {
                $hideRaids = eval(PSI_PLUGIN_RAID_HIDE_DEVICES);
            } else {
                $hideRaids = array(PSI_PLUGIN_RAID_HIDE_DEVICES);
            }
        }
        foreach ($this->_result['devices'] as $key=>$device) {
            if (!in_array(ltrim($key, "/"), $hideRaids, true)) {
                $dev = $this->xml->addChild("Raid");
                $dev->addAttribute("Device_Name", ltrim($key, "/")); //for megactl and megasasctl conflicts
                $dev->addAttribute("Program", $device["prog"]);
                if (isset($device['level'])) $dev->addAttribute("Level", strtolower($device["level"]));
                $dev->addAttribute("Status", strtolower($device["status"]));
                if (isset($device['name'])) $dev->addAttribute("Name", $device["name"]);
                if (isset($device['size'])) $dev->addAttribute("Size", $device["size"]);
                if (isset($device['stride'])) $dev->addAttribute("Stride", $device["stride"]);
                if (isset($device['subsets'])) $dev->addAttribute("Subsets", $device["subsets"]);
                if (isset($device['devs'])) $dev->addAttribute("Devs", $device["devs"]);
                if (isset($device['spares'])) $dev->addAttribute("Spares", $device["spares"]);

                if (isset($device['chunk_size'])) $dev->addAttribute("Chunk_Size", $device["chunk_size"]);
                if (isset($device['pers_superblock'])) $dev->addAttribute("Persistend_Superblock", $device["pers_superblock"]);
                if (isset($device['algorithm'])) $dev->addAttribute("Algorithm", $device["algorithm"]);
                if (isset($device['registered'])) $dev->addAttribute("Disks_Registered", $device["registered"]);
                if (isset($device['active'])) $dev->addAttribute("Disks_Active", $device["active"]);
                if (isset($device['controller'])) $dev->addAttribute("Controller", $device["controller"]);
                if (isset($device['battery'])) $dev->addAttribute("Battery", $device["battery"]);
                if (isset($device['supported'])) $dev->addAttribute("Supported", $device["supported"]);
                if (isset($device['readpolicy'])) $dev->addAttribute("ReadPolicy", $device["readpolicy"]);
                if (isset($device['writepolicy'])) $dev->addAttribute("WritePolicy", $device["writepolicy"]);
                if (isset($device['cache_size'])) $dev->addAttribute("Cache_Size", $device["cache_size"]);
                if (isset($device['bad_blocks'])) $dev->addAttribute("Bad_Blocks", $device["bad_blocks"]);

                if (isset($device['action'])) {
                    $action = $dev->addChild("Action");
                    $action->addAttribute("Name", $device['action']['name']);
                    if (isset($device['action']['percent'])) $action->addAttribute("Percent", $device['action']['percent']);

                    if (isset($device['action']['finish_time'])) $action->addAttribute("Time_To_Finish", $device['action']['finish_time']);
                    if (isset($device['action']['finish_unit'])) $action->addAttribute("Time_Unit", $device['action']['finish_unit']);

                }
                $disks = $dev->addChild("RaidItems");
                if (isset($device['items']) && (sizeof($device['items'])>0)) foreach ($device['items'] as $disk) {
                    if (isset($disk['name'])) {
                        $disktemp = $disks->addChild("Item");
                        $disktemp->addAttribute("Name", $disk['name']);
                        // if (isset($disk['raid_index'])) $disktemp->addAttribute("Index", $disk['raid_index']);
                        if (isset($disk['parentid'])) $disktemp->addAttribute("ParentID", $disk['parentid']);
                        if (isset($disk['type'])) $disktemp->addAttribute("Type", $disk['type']);
                        // if (in_array(strtolower($device["status"]), array('ok', 'optimal', 'active', 'online', 'degraded'))) {
                            $disktemp->addAttribute("Status", $disk['status']);
                        //} else {
                        //    $disktemp->addAttribute("Status", "W");
                        //}
                        if (isset($disk['info'])) $disktemp->addAttribute("Info", $disk['info']);
                    }
                }
            }
        }

        return $this->xml->getSimpleXmlElement();
    }
1353415
function to_xml(){
		if ($this->skip) return false;
		
		$data = array(
			'id' => $this->get_id()
		);
		for ($i=0; $i<sizeof($this->config->text); $i++){
			$extra = $this->config->text[$i]["name"];
			$data[$extra]=$this->data[$extra];
			if (is_null($data[$extra]))
			    $data[$extra] = "";
		}

		if ($this->userdata !== false)
			foreach ($this->userdata as $key => $value){
				if ($value === null)
					$data[$key]="";
				$data[$key]=$value;
			}

		return $data;
	}
837139
public function parse()
    {
        $counter = 0;
        $continue = true;
        while ($continue) {
            $continue = $this->readNextChunk();

            ++$counter;
            if (!isset($this->rootNode)) {
                // Find root node
                if (isset($this->customRootNode)) {
                    $customRootNodePos = strpos($this->chunk, "<{$this->customRootNode}");
                    if (false !== $customRootNodePos) {
                        // Found custom root node
                        // Support attributes
                        $closer = strpos(substr($this->chunk, $customRootNodePos), '>');
                        $readFromChunkPos = $customRootNodePos + $closer + 1;

                        // Custom child node?
                        if (isset($this->customChildNode)) {
                            // Find it in the chunk
                            $customChildNodePos = strpos(substr($this->chunk, $readFromChunkPos), "<{$this->customChildNode}");
                            if (false !== $customChildNodePos) {
                                // Found it!
                                $readFromChunkPos = $readFromChunkPos + $customChildNodePos;
                            } else {
                                // Didn't find it - read a larger chunk and do everything again
                                continue;
                            }
                        }

                        $this->rootNode = $this->customRootNode;
                        $this->readFromChunkPos = $readFromChunkPos;
                    } else {
                        // Clear chunk to save memory, it doesn't contain the root anyway
                        $this->readFromChunkPos = 0;
                        $this->chunk = '';
                        continue;
                    }
                } else {
                    // XML1.0 standard allows almost all Unicode characters even Chinese and Cyrillic.
                    // see: http://en.wikipedia.org/wiki/XML#International_use
                    preg_match('/<([^>\?]+)>/', $this->chunk, $matches);
                    if (isset($matches[1])) {
                        // Found root node
                        $this->rootNode = $matches[1];
                        $this->readFromChunkPos = strpos($this->chunk, $matches[0]) + strlen($matches[0]);
                    } else {
                        // Clear chunk to save memory, it doesn't contain the root anyway
                        $this->readFromChunkPos = 0;
                        $this->chunk = '';
                        continue;
                    }
                }
            }

            while (true) {
                $fromChunkPos = substr($this->chunk, $this->readFromChunkPos);

                // Find element
                // XML1.0 standard allows almost all Unicode characters even Chinese and Cyrillic.
                // see: http://en.wikipedia.org/wiki/XML#International_use
                preg_match('/<([^>]+)>/', $fromChunkPos, $matches);
                if (isset($matches[1])) {
                    // Found element
                    $element = $matches[1];

                    // Is there an end to this element tag?
                    $spacePos = strpos($element, ' ');
                    $crPos = strpos($element, "\r");
                    $lfPos = strpos($element, "\n");
                    $tabPos = strpos($element, "\t");

                    // find min. (exclude false, as it would convert to int 0)
                    $aPositionsIn = array($spacePos, $crPos, $lfPos, $tabPos);
                    $aPositions = array();
                    foreach ($aPositionsIn as $iPos) {
                        if (false !== $iPos) {
                            $aPositions[] = $iPos;
                        }
                    }

                    $minPos = $aPositions === array() ? false : min($aPositions);

                    if (false !== $minPos && 0 != $minPos) {
                        $sElementName = substr($element, 0, $minPos);
                        $endTag = '</'.$sElementName.'>';
                    } else {
                        $sElementName = $element;
                        $endTag = "</$sElementName>";
                    }

                    $endTagPos = false;

                    // try selfclosing first!
                    // NOTE: selfclosing is inside the element
                    $lastCharPos = strlen($element) - 1;
                    if ('/' == substr($element, $lastCharPos)) {
                        $endTag = '/>';
                        $endTagPos = $lastCharPos;

                        $iPos = strpos($fromChunkPos, '<');
                        if (false !== $iPos) {
                            // correct difference between $element and $fromChunkPos
                            // "+1" is for the missing '<' in $element
                            $endTagPos += $iPos + 1;
                        }
                    }

                    if (false === $endTagPos) {
                        $endTagPos = strpos($fromChunkPos, $endTag);
                    }

                    if (false !== $endTagPos) {
                        // Found end tag
                        $endTagEndPos = $endTagPos + strlen($endTag);
                        $elementWithChildren = trim(substr($fromChunkPos, 0, $endTagEndPos));

                        $continueParsing = $this->processNode($elementWithChildren, $sElementName, $this->nodeIndex++);
                        $this->chunk = substr($this->chunk, strpos($this->chunk, $endTag) + strlen($endTag));
                        $this->readFromChunkPos = 0;

                        if (isset($continueParsing) && false === $continueParsing) {
                            $this->chunkCompleted();
                            break 2;
                        }
                    } else {
                        break;
                    }
                } else {
                    break;
                }
            }
            $this->chunkCompleted();
        }

        return isset($this->rootNode);
        fclose($this->handle);
    }
387311
public function main()
    {
        // cargar XML y extraer arreglo con datos de carátula y DTEs
        $EnvioDte = new \sasco\LibreDTE\Sii\EnvioDte();
        $EnvioDte->loadXML(file_get_contents($this->args['xml']));
        $Caratula = $EnvioDte->getCaratula();
        $Documentos = $EnvioDte->getDocumentos();
        // procesar cada DTEs e ir creando los archivos PDF
        foreach ($Documentos as $DTE) {
            if (!$DTE->getDatos())
                $this->error('No se pudieron obtener los datos de uno de los DTE del XML');
            $this->out('Generando PDF para DTE '.$DTE->getID());
            $pdf = new \sasco\LibreDTE\Sii\Dte\PDF\Dte($this->args['papel']);
            $pdf->setFooterText();
            if ($this->args['logo'])
                $pdf->setLogo($this->args['logo']);
            $pdf->setResolucion(['FchResol'=>$Caratula['FchResol'], 'NroResol'=>$Caratula['NroResol']]);
            $pdf->setWebVerificacion($this->args['web']);
            $pdf->agregar($DTE->getDatos(), $DTE->getTED());
            if (isset($this->args['cedible'])) {
                $pdf->setCedible(true);
                $pdf->agregar($DTE->getDatos(), $DTE->getTED());
            }
            $pdf->Output($this->args['dir'].'/dte_'.$Caratula['RutEmisor'].'_'.$DTE->getID().'.pdf', 'F');
        }
        return 0;
    }
639869
public function buildXML()
    {
        $xml = new EncodingRequest();

        $request = $xml->setDomQuery($this->client->getConfig('userid'), $this->client->getConfig('userkey'), $this->getName());

        foreach ($this->getOperation()->getParams() as $name => $arg) {

            if ($this->get($name) === true) {
                $request->appendChild($xml->createElement($name));
            } else {
                if (! is_null($this->get($name)) && $this->get($name) !== false) {

                    if (! is_array($this->get($name))) {
                        // Non Array Type - String, Integer, etc ..

                        $request->appendChild($xml->createElement($name, $this->get($name)));
                    } else {

                        if ($name == "source") {
                            // Build "Flat" Array to XML

                            foreach ($this->get($name) as $key => $value) {
                                $request->appendChild($xml->createElement($name, $value));
                            }
                        } else {
                            // Build Array to XML

                            $arrayRoot = $request->appendChild($xml->createElement($name));

                            foreach ($this->get($name) as $key => $value) {

                                if (! is_array($value)) {
                                    $arrayRoot->appendChild($xml->createElement($key, $value));
                                } else {
                                    if ($key == "destination") {
                                        // Build "Flat" Array to XML in a sub Element
                                        foreach ($value as $subValue) {
                                            $arrayRoot->appendChild($xml->createElement($key, $subValue));
                                        }
                                    } else {
                                        $arraySubRoot = $arrayRoot->appendChild($xml->createElement($key));

                                        foreach ($value as $subKey => $subValue) {
                                            $arraySubRoot->appendChild($xml->createElement($subKey, $subValue));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return $xml;
    }
858478
protected function parse(): void
    {
        // add the root node
        $this->root = new HtmlNode('root');
        $activeNode = $this->root;
        while ( ! is_null($activeNode)) {
            $str = $this->content->copyUntil('<');
            if ($str == '') {
                $info = $this->parseTag();
                if ( ! $info['status']) {
                    // we are done here
                    $activeNode = null;
                    continue;
                }

                // check if it was a closing tag
                if ($info['closing']) {
                    $foundOpeningTag  = true;
                    $originalNode     = $activeNode;
                    while ($activeNode->getTag()->name() != $info['tag']) {
                        $activeNode = $activeNode->getParent();
                        if (is_null($activeNode)) {
                            // we could not find opening tag
                            $activeNode = $originalNode;
                            $foundOpeningTag = false;
                            break;
                        }
                    }
                    if ($foundOpeningTag) {
                        $activeNode = $activeNode->getParent();
                    }
                    continue;
                }

                if ( ! isset($info['node'])) {
                    continue;
                }

                /** @var AbstractNode $node */
                $node = $info['node'];
                $activeNode->addChild($node);

                // check if node is self closing
                if ( ! $node->getTag()->isSelfClosing()) {
                    $activeNode = $node;
                }
            } else if ($this->options->whitespaceTextNode ||
                trim($str) != ''
            ) {
                // we found text we care about
                $textNode = new TextNode($str, $this->options->removeDoubleSpace);
                $activeNode->addChild($textNode);
            }
        }
    }
593893
public function toXML()
	{
		$document = new \DOMDocument("1.0", 'UTF-8');

		$gpx = $document->createElementNS("http://www.topografix.com/GPX/1/1", "gpx");
		$gpx->setAttribute("version", "1.1");
		$gpx->setAttribute("creator", $this->creator ? $this->creator : phpGPX::getSignature());

		ExtensionParser::$usedNamespaces = [];

		if (!empty($this->metadata)) {
			$gpx->appendChild(MetadataParser::toXML($this->metadata, $document));
		}

		foreach ($this->waypoints as $waypoint) {
			$gpx->appendChild(PointParser::toXML($waypoint, $document));
		}

		foreach ($this->routes as $route) {
			$gpx->appendChild(RouteParser::toXML($route, $document));
		}

		foreach ($this->tracks as $track) {
			$gpx->appendChild(TrackParser::toXML($track, $document));
		}

		if (!empty($this->extensions)) {
			$gpx->appendChild(ExtensionParser::toXML($this->extensions, $document));
		}

		// Namespaces
		$schemaLocationArray = [
			'http://www.topografix.com/GPX/1/1',
			'http://www.topografix.com/GPX/1/1/gpx.xsd'
		];

		foreach (ExtensionParser::$usedNamespaces as $usedNamespace) {
			$gpx->setAttributeNS(
				"http://www.w3.org/2000/xmlns/",
				sprintf("xmlns:%s", $usedNamespace['prefix']),
				$usedNamespace['namespace']
			);

			$schemaLocationArray[] = $usedNamespace['namespace'];
			$schemaLocationArray[] = $usedNamespace['xsd'];
		}

		$gpx->setAttributeNS(
			'http://www.w3.org/2001/XMLSchema-instance',
			'xsi:schemaLocation',
			implode(" ", $schemaLocationArray)
		);

		$document->appendChild($gpx);

		if (phpGPX::$PRETTY_PRINT) {
			$document->formatOutput = true;
			$document->preserveWhiteSpace = true;
		}
		return $document;
	}
8756
public function xml()
    {
        foreach ($this->_result as $bat_item) {
            $xmlbat = $this->xml->addChild("Bat");
            if (isset($bat_item['name'])) {
                $xmlbat->addAttribute("Name", $bat_item['name']);
            }
            if (isset($bat_item['model']) && ($bat_item['model'] !== "1")) {
                $xmlbat->addAttribute("Model", $bat_item['model']);
            }
            if (defined('PSI_PLUGIN_BAT_SHOW_SERIAL') && PSI_PLUGIN_BAT_SHOW_SERIAL
               && isset($bat_item['serialnumber'])
               && ($bat_item['serialnumber'] !== "")
               && ($bat_item['serialnumber'] !== "0")
               && ($bat_item['serialnumber'] !== "0000")) {
                $xmlbat->addAttribute("SerialNumber", $bat_item['serialnumber']);
            }
            if (isset($bat_item['manufacturer'])) {
                $xmlbat->addAttribute("Manufacturer", $bat_item['manufacturer']);
            }
            if ((!isset($bat_item['remaining_capacity']) || (isset($bat_item['full_capacity']) && ($bat_item['full_capacity'] == 0))) &&
                isset($bat_item['capacity']) && ($bat_item['capacity']>=0)) {
                if (isset($bat_item['capacity_unit']) && ($bat_item['capacity_unit'] !== "???")
                   && (isset($bat_item['full_capacity']) && ($bat_item['full_capacity'] > 0))) {
                    $xmlbat->addAttribute("CapacityUnit", $bat_item['capacity_unit']);
                    $xmlbat->addAttribute("RemainingCapacity", round($bat_item['capacity']*$bat_item['full_capacity']/100));
                    $xmlbat->addAttribute("FullCapacity", $bat_item['full_capacity']);
                    if (isset($bat_item['design_capacity'])) {
                        $xmlbat->addAttribute("DesignCapacity", $bat_item['design_capacity']);
                    }
                } else {
                    $xmlbat->addAttribute("FullCapacity", 100);
                    $xmlbat->addAttribute("RemainingCapacity", $bat_item['capacity']);
                    $xmlbat->addAttribute("CapacityUnit", "%");
                }
            } else {
                if (isset($bat_item['full_capacity'])) {
                    if (isset($bat_item['design_capacity'])) {
                        $xmlbat->addAttribute("DesignCapacity", $bat_item['design_capacity']);
                    }
                    $xmlbat->addAttribute("FullCapacity", $bat_item['full_capacity']);
                } elseif (isset($bat_item['design_capacity'])) {
                    $xmlbat->addAttribute("FullCapacity", $bat_item['design_capacity']);
                }
                if (isset($bat_item['remaining_capacity'])) {
                    $xmlbat->addAttribute("RemainingCapacity", $bat_item['remaining_capacity']);
                }
                if (isset($bat_item['capacity_unit'])) {
                    $xmlbat->addAttribute("CapacityUnit", $bat_item['capacity_unit']);
                }
            }
            if (isset($bat_item['design_voltage']) && ($bat_item['design_voltage']>0)) {
                $xmlbat->addAttribute("DesignVoltage", $bat_item['design_voltage']);
                if (isset($bat_item['design_voltage_max']) && ($bat_item['design_voltage_max']>0) && ($bat_item['design_voltage_max'] != $bat_item['design_voltage'])) {
                    $xmlbat->addAttribute("DesignVoltageMax", $bat_item['design_voltage_max']);
                }
            } elseif (isset($bat_item['design_voltage_max']) && ($bat_item['design_voltage_max']>0)) {
                $xmlbat->addAttribute("DesignVoltage", $bat_item['design_voltage_max']);
            }
            if (isset($bat_item['present_voltage'])) {
                $xmlbat->addAttribute("PresentVoltage", $bat_item['present_voltage']);
            }
            if (isset($bat_item['charging_state'])) {
                $xmlbat->addAttribute("ChargingState", $bat_item['charging_state']);
            } else {
                if (isset($bat_item['charging_state_i'])) {
                    $xmlbat->addAttribute("ChargingState", 'Charging');
                } elseif (!isset($bat_item['charging_state_e'])) {
                    $xmlbat->addAttribute("ChargingState", 'Discharging');
                } elseif (isset($bat_item['charging_state_f'])) {
                    $xmlbat->addAttribute("ChargingState", 'Fully Charged');
                } else {
                    $xmlbat->addAttribute("ChargingState", 'Unknown state');
                }
            }
            if (isset($bat_item['battery_type'])) {
                $xmlbat->addAttribute("BatteryType", $bat_item['battery_type']);
            }
            if (isset($bat_item['battery_temperature'])) {
                $xmlbat->addAttribute("BatteryTemperature", $bat_item['battery_temperature']);
            }
            if (isset($bat_item['battery_condition'])) {
                $xmlbat->addAttribute("BatteryCondition", $bat_item['battery_condition']);
            }
            if (isset($bat_item['cycle_count'])) {
                $xmlbat->addAttribute("CycleCount", $bat_item['cycle_count']);
            }
        }

        return $this->xml->getSimpleXmlElement();
    }
1234241
function(nombre, controlador, tags, opciones) {
    // Se establecen los objetos comunes a todos los dispositivos
    this.info = Object();
    this.info.nombre = nombre;
    this.conectado = false;
    this.noErrores = true;
    this.cola = new objCola();
    this.funciones = new funciones(this);
    this.log = new log(this.info.nombre);
    this.tags = tags;
    this.tiposMB = {
        BYTE: {bits: 8, funcion: 'Int8', endian: false},
        INT: {bits: 16, funcion: 'Int16', endian: true},
        UINT: {bits: 16, funcion: 'UInt16', endian: true},
        DINT: {bits: 32, funcion: 'Int32', endian: true},
        UDINT: {bits: 32, funcion: 'UInt32', endian: true}, 
        FLOAT: {bits: 32, funcion: 'Float', endian: true},
        DOUBLE: {bits: 64, funcion: 'Double', endian: true}
    }
    new require('./drivers/'+controlador+'/driver') (this); // Se integran las funciones del driver con el dispositivo actual
    utilidades.mezclarObjetos(opciones, this.info); // Se establecen los objetos particulares de cada dispositivo
    
    this.conectarRecursiva(); // Se conecta el dispositivo
    
    
    
    
    /*
     * Se establecen los eventos o Listeners que serán ejecutados en TODOS los dispositivos, sean del driver que sea
     */
    utilidades.eventos(this, {
        conexion: function() {
            this.conectado = true;
            this.comenzarCiclo();
            this.comprobarConexion();
            
            this.log.info("Conectado");
            this.emit("conectado");
        },
        desconexion: function() {
            if (this.conectado) {
                this.conectado = false;
               
                this.cola.vaciar();
                
                this.log.error("Desconectado");
                this.emit("desconectado");
                this.conectarRecursiva();
            }
        },
        datosRecibidos: function(datos) {
            var buffer = utilidades.extractorBuffer(datos, this.estructuraCabecera, this.tiposMB, this.bytesPorPosicion, this.endian, this.noErrores);   
            if (typeof this.cola.operaciones[buffer.operacion] === 'undefined') {
                this.cola.prepararCola();
                return false;
            }
            
            var numOperacion = buffer.operacion;
            var operacion = this.cola.operaciones[numOperacion];
            var numPaquete = operacion.paquete;
            var paquete = this.cola.paquetes[numPaquete];

            if ((paquete.operaciones.lastIndexOf(numOperacion) === -1) || (typeof this.funciones[paquete.funcion+"Callback"] === 'undefined')) {
                this.cola.prepararCola();
                return false;
            }
            
            var informacion = this.funciones[paquete.funcion+"Callback"](buffer, numOperacion, operacion, numPaquete, paquete);            
            if (paquete.operaciones.length == 1) {
                if (this.cola.quitarPaquete(numPaquete)) {
                    if (typeof paquete.callback == 'function') {
                        if (typeof informacion == 'object') {
                            var array = utilidades.obj2arr(informacion);
                        }

                        paquete.callback.apply(this, array);
                    }
                }
            } else {
                this.cola.quitarOperacion(numOperacion);
            }
            
            this.cola.prepararCola();
            return true;
        },
        error: function() {
            if (this.conectado) {
                this.log.error("Se ha producido un error. Reconectamos el dispositivo...");
                this.emit("desconexion");
            }
        }
    });

    // Alias para los eventos
    this.on("conectado", function() {
        this.emit("connected");
    });
    this.on("desconectado", function() {
        this.emit("disconnected");
    });
    
    
    events.call(this); // Función de llamada a los eventos personalizados
}