PHP XML Import Problem

Discussion in 'PHP' started by Ian, Nov 21, 2008.

  1. #1
    I'm trying to import an XML file into my database, but am running into a problem as it tries to parse it. The XML file has multiple values, but not every SKU contains a value in that field (for example sometimes the value 2 field is empty) so I'm getting a "Column count doesn't match value count" error each time it comes to a value in the xml file that isn't there. What code do I need to add to get it to ignore it and insert a blank field and then continue on?"

    Here's the code in question:

    <?php
    // initialize some variables
    $currentTag = "";

    // this array will hold the values for the SQL statement
    $values = array();

    // this array will hold allowed fields/elements
    $allowedFields = array("sku", "value1", "value2");

    // XML file to parse
    $xml_file="file.xml";

    // database parameters
    $host = "localhost";
    $user = "name";
    $pass = "pass";
    $db = "db";
    $table = "table";

    // called when parser finds start tag
    function startElementHandler($parser, $name, $attributes)
    {
    global $currentTag;
    $currentTag = $name;
    }

    // called when parser finds end tag
    function endElementHandler($parser, $name)
    {
    global $values, $currentTag;
    // import database link and table name
    global $connection, $table;

    // if ending <item> tag
    // implies end of record
    if (strtolower($name) == "xmlfield")
    {
    // generate the query string
    $query = "INSERT INTO table ";
    $query .= "(sku,value1,value2) ";
    $query .= "VALUES(\"" . join("\", \"", $values) . "\");";

    // uncomment for debug
    // print $query;

    // execute query
    $result = mysql_query($query);

    // reset all internal counters and arrays
    $values = array();
    $currentTag = "";
    }

    }

    // called when parser finds cdata
    function characterDataHandler($parser, $data)
    {

    global $currentTag, $values, $allowedFields;
    // lowercase tag name
    $currentTag = strtolower($currentTag);

    // look for tag in $allowedFields[] array
    // to see if it is to be included in query
    if (in_array($currentTag, $allowedFields) && trim($data) != "")
    {
    // add field=>value pairs to $values array
    $values[$currentTag] = mysql_escape_string($data);
    }
    }

    // initialize parser
    $xml_parser = xml_parser_create();

    // turn off whitespace processing
    xml_parser_set_option($xml_parser,XML_OPTION_SKIP_WHITE, TRUE);
    // turn on case folding
    xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, FALSE);

    // set callback functions
    xml_set_element_handler($xml_parser, "startElementHandler", "endElementHandler");
    xml_set_character_data_handler($xml_parser, "characterDataHandler");

    // open connection to database
    $connection = mysql_connect($host, $user, $pass) or die ("Unable to connect!");
    mysql_select_db($db) or die ("Unable to select database!");

    // read XML file
    if (!($fp = fopen($xml_file, "r")))
    {
    die("File I/O error: $xml_file");
    }

    // parse XML
    while ($data = fread($fp, 4096))
    {
    // error handler
    if (!xml_parse($xml_parser, $data, feof($fp)))
    {
    $error_code = xml_get_error_code($xml_parser);
    die("XML parser error (error code " . $error_code . "): " . xml_error_string($error_code) . "<br>Error occurred at line " . xml_get_current_line_number($xml_parser));
    }
    }

    // all done, clean up!
    xml_parser_free($xml_parser);
    mysql_close($connection);

    ?>

    Thank you in advance for your assistance!
     
    Ian, Nov 21, 2008 IP
  2. AdultProfiles

    AdultProfiles Peon

    Messages:
    54
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #2
    Why you don't try to use simplexml extension (PHP 5>) ?
    its very easy to use
     
    AdultProfiles, Nov 21, 2008 IP
  3. juust

    juust Peon

    Messages:
    214
    Likes Received:
    11
    Best Answers:
    0
    Trophy Points:
    0
    #3
    after you reset the values array :
    // reset all internal counters and arrays
    $values = array();
    $currentTag = "";

    for($i=0;$i<count($allowedFields);$i++) {
    $values[$allowedFields[$i]]='';
    }

    that pre-fills the $values-array with empty strings
    using the fieldnames of the $allowedFields array

    that might work ?
     
    juust, Nov 21, 2008 IP
  4. Ian

    Ian Well-Known Member

    Messages:
    409
    Likes Received:
    14
    Best Answers:
    0
    Trophy Points:
    125
    #4
    Thank you for the response, I really appreciate it. Unfortunately I implemented it but still got the same error. This one has me scratching my head....do you have another thought of what it could be?
     
    Ian, Nov 21, 2008 IP
  5. juust

    juust Peon

    Messages:
    214
    Likes Received:
    11
    Best Answers:
    0
    Trophy Points:
    0
    #5
    could you remove the slashes
    print $query
    and echo the query it generates ?

    That might shed some light on it.

    Apart from that I'd consider using simpleXml :)
     
    juust, Nov 21, 2008 IP