Greetings.

I'm having some problems with PHP (5.1.2) DOM Functions.

Here's the XML file I'm reading:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE config SYSTEM "config.dtd">
<config>
    <host code='h0001' name='local' ipaddr='127.0.0.1'>
        <connection code='c0001' name='test'>
            <database type='postgresql'>
                <name>dbone</name>
                <user>itsme</user>
                <pass>youwish</pass>
            </database>
        </connection>
        <connection code='c0002' name='test2'>
            <database type='mysql'>
                <name>anydb</name>
                <user>anyuser</user>
                <pass>tryagain</pass>
            </database>
        </connection>
    </host>
</config>

And I have a class I'm working on to read the XML file. The constructor receives two parameters: host code and connection code. All works fine if I try with 'h0001' and 'c0001' but it fails if I try with 'h0001' and 'c0002', meaning I was doing something wrong reading the "connection" child element. Here's how the code looked like at first:

<?php
final class dbMethods
{
    protected $dbHost,
              $dbPort,
              $dbName,
              $dbUser,
              $prefix;

private $xmlDocument,
        $primaryElement,
        $aliasElement,
        $element,
        $dbPass;

function __construct($hostCode, $connCode)
{
    $this->xmlDocument = new domDocument();
    $this->xmlDocument->load('conf/config.xml') or die('Impossible to load the setup file.');

    if ($this->xmlDocument->validate())
    {
        $this->primaryElement = $this->xmlDocument->getElementsByTagName('host');

        for($a = 0; $a < count($this->primaryElement); $a++)
        {
            if ($this->primaryElement->item($a)->getAttribute('code') == $hostCode)
            {
                $this->ipaddr = $this->primaryElement->item($a)->getAttribute('ipaddr');

                $this->connections = $this->primaryElement->item($a)->getElementsByTagName('connection');

                for($c = 0; $c < count($this->connections); $c++)
                {
                    echo "Debug: ".$this->connections->item($c)->getAttribute('code')."<HR>";

                    if ($this->connections->item($c)->getAttribute('code') == $connCode)
                    {
                        $this->db = $this->connections->item($c)->getElementsByTagName('database');

                        $this->dbType = $this->db->item(0)->getAttribute('type');

                        if ($this->dbType == 'postgresql')
                        {
                            $this->prefix = 'pg';
                        }
                        else if ($this->dbType == 'mysql')
                        {
                            $this->prefix = 'mysql';
                        }

                        $this->dbElements = $this->db->item(0)->getElementsByTagName('*');

                        $this->dbName = $this->dbElements->item(0)->nodeValue;
                        $this->dbUser = $this->dbElements->item(1)->nodeValue;
                        $this->dbPass = $this->dbElements->item(2)->nodeValue;
                    }
                }
            }
        }

        echo $this->dbName . "<BR>" . $this->dbUser . "<BR>" . $this->dbPass . "<HR>";
    }
    else
    {
        die("Invalid XML Document.");
    }
}
}
?>

So, after re-reading the documentation I've realized I should'nt use

$this->connections = $this->primaryElement->item($a)->getElementsByTagName('connection');

but instead use this:

$this->connections = $this->primaryElement->item($a)->childNodes;

which, according to the documentation, should bring me a DOMNodeList. Well, it seems that it's not doing that, since I get the following error:

Fatal error: Call to undefined method DOMText::getAttribute() in C:\foo\bar\code\include\class\dbMethods.class.php on line 35

This line is the one who echoes the code attribute for connection.

Is this a bug or am I missing something here?

TIA,

    I believe I've truly found a bug. I've made some var_dumps and found that:

    1) $this->primaryElement is a DOMNodeList, which is correct.
    2) $this->connections is a DOMNodeList, which is also correct.

    Problem is that $this->connections($c) returns a DOMText instead of a DOMNodeElement.

    Another thing I've realized is that if I put another "set" of information on the xml file (another set beginning with the tag host) the first for loop just doesn't get it.

    Any clues?

    TIA,

      Well, the first node of the <connections> element is a text node; it contains the whitespace between the end of the <connections> tag and the start of the first <connection> tag. Perhaps if you switched $this->xmlDocument->preserveWhiteSpace = false after constructing it?

      The main problem is that you're trying count($this->primaryElement) etc., but that will return 1, because $this->primaryElement is not an array of nodes, it's a DOMNodeList object. So just as you use $this->primaryElement->item($i) and not $this->primaryElement[$i], you use

      for($a = 0; $a < $this->primaryElement->length; $a++)

        Yes, I've realized the count x length part a moment ago, which solved the "adding new hosts" issue.

        Thanks a lot. The preserveWhiteSpace really solved the problem. 🙂

        Best regards,

          Write a Reply...