XML Parser:为什么我在循环中获取数据?

时间:2013-06-14 20:40:35

标签: php xml parsing xml-parsing

希望任何人都可以帮助我...我想将记录从xml文件导入到sql数据库中。第一个记录保存正确,第二个记录用两个记录的数据填充,第三个记录用三个记录的数据等等...... 我做错了什么?我是菜鸟,请在回复中考虑一下。 因为我真的不知道在哪里找到问题,我必须展示整个php代码。我真的需要你的帮助 - 先谢谢!!

这是我的php文件:

<?php
defined('_JEXEC') or die('Restricted access');

/**
* Parser Class
*/
class Parser
{
var $dbo;
var $partner;

function __construct($dbo, $parser, $id) {
    $this->dbo = $dbo;
    $this->partner = new stdClass();
    $this->partner->name = $parser;
    $this->partner->id = $id;
}

function go() {
    error_reporting(E_ALL);

    // creating parser object
    $xml_parser = xml_parser_create('UTF-8');

    // set encoding to UTF-8
    xml_parser_set_option($xml_parser,
            XML_OPTION_TARGET_ENCODING,
            'UTF-8');

    // initializing the handler class
    $handler = new XMLHandlerClass(
            $this->dbo,
            $this->partner);

    // setting up the handlers
    xml_set_element_handler($xml_parser,
            array($handler, 'startElement'),
            array($handler, 'endElement'));
    xml_set_character_data_handler($xml_parser,
            array($handler, 'contents'));

    // path to the xml file
    $file = JPATH_SITE.DS.'tmp'.DS.'routes.xml';

    // open the file to read
    if (!($fp = fopen($file, "r"))) {
        die('konnte xml nicht öffnen');
        return false;
    }

    // read line after line from the xml file
    $data = null;
    while ($data = fgets($fp, 100000)) {
        if (!xml_parse($xml_parser, $data, feof($fp))) {
            die(sprintf("XML error: %s at line %d",
                xml_error_string(xml_get_error_code($xml_parser)),
                xml_get_current_line_number($xml_parser)));
        }
    }

    // free the xml parser
    xml_parser_free($xml_parser);

    // every thing fine?
    return true;
}
}

/**
* XML Handler Class
*/
class XMLHandlerClass
{
var $dbo;
var $partner;

var $element;

var $saveCounter = 0;
var $clearCounter = 0;

var $cabintype;
var $counterPrice = 0;

var $counterRoute = 0;

var $item;

var $api;

function __construct($dbo, $partner) {

    // save params
    $this->dbo = $dbo;
    $this->partner = $partner;

    // include api
    include_once JPATH_COMPONENT_ADMINISTRATOR
            .DS.'api'.DS.'KreuzfahrtenAPI.php';

    // initialize api
    $this->api = new KreuzfahrtenAPI($this->dbo,
            $this->partner->name,
            $this->partner->id);
}

function startElement($parser, $name, $attrs) {
    // don't give up
    set_time_limit(120);

    // get the name
    $this->element = strtolower($name);

    // bevor das speichern der tripps beginnt,
    // aber eigentlich schon die routen informationen da sind
    // soll die dauer noch um 1 gekürzt werden
    if ($this->element == "listoftrips") {
        $this->item['dauer'] -= 1;
    }
}

function endElement($parser, $name) {

    // don't give up
    set_time_limit(120);

    // get the name
    $name = strtolower($name);

    // counter hochzählen
    switch ($name) {
        case "port":
            $this->counterRoute++;
            break;
        case "cabin":
            $this->counterPrice++;
            break;
        case "trip":
            $this->saveCounter++;
            $this->save();
            break;
        case "route":
            $this->clearCounter++;
            $this->clear();
            break;
    }
}

function contents($parser, $data) {

    // remove quots
    $data = $this->reEn($data);

    // assign the $data by the $this->element
    switch ($this->element) {
        case "routeid":
            $this->item['routeid'] .= $data;
            break;
        case "name":
            $this->item['titel'] .= $data;
            break;
        case "duration":
            $this->item['dauer'] .= $data;
            break;
        case "port":
            if ($this->counterRoute != 0 && $this->counterRoute != 1) {
                $this->item['route'][$this->counterRoute-2] .= $data;
            }
            break;
        case "priceoverview":
            if ($data == "Einzel") break;
            switch ($data) {
                case "bestinsidecabinprice":
                    $this->cabintype = "Innenkabine";
                    break;
                case "bestoutsidecabinprice":
                    $this->cabintype = "Außenkabine";
                    break;
                case "bestsuitecabinprice":
                    $this->cabintype = "Suite";
                    break;
                case "bestbalconycabinprice":
                    $this->cabintype = "Balkonkabine";
                    break;
                default:
                    die('Kein passender Kabinentyp '.$data);
                    break;
            }
            break;
        case "bestprice":
            $cabinetype = $this->cabintype;
            $this->item['prices'][$cabinetype][$this->counterPrice] .= 
            str_replace(',', '.', $data);
            unset($cabinetype);
            break;
        case "tripbegins":
            $this->item['beginn'] .= $data;
            break;
        case "tripends":
            $this->item['ende'] .= $data;
            break;
        case "destinationname":
            $this->item['zielgebiet'] .= $data;
            break;
        case "shipname":
            $this->item['schiff'] .= $data;
            break;
    }
}

function reEn($subject) {
    $toDel = array (
        '"',
        "'"
    );
    $toRe = array(
        '',
        ''
    );
    $subject = str_replace($toDel, $toRe, $subject);
    return $subject;
}

function clear($error = false) {
    if ($error) {
        $title = "ERROR:Clear";
        $description = "ITEM:\n"
            .$this->api->implodeItem($this->item);
        $this->api->setErrorMsg($title,$description);
    }

    $this->element = null;
    $this->item = null;
    $this->cabintype = null;
    $this->counterPrice = 0;
    $this->counterRoute = 0;
}

function save() {
    // neues zeitlimit setzen
    set_time_limit(120);

    // prüfe ob alle daten vorhanden sind
    if (empty($this->item['titel'])
            || empty($this->item['routeid'])
            || empty($this->item['dauer'])
            || !is_array($this->item['route'])
            || !is_array($this->item['prices'])
            || empty($this->item['beginn'])
            || empty($this->item['ende'])
            || empty($this->item['zielgebiet'])
            || empty($this->item['schiff'])
                    ) {
        $this->clear(TRUE);
        return false;
    } else {
        // daten für api vorbereichten

        // -- url
        $this->item['url'] = "www.domain.com/?fuseaction=product.showroute="
                .$this->item['routeid']
                ."&ID=112201000000";
        // -- datum
        $this->item['beginn'] = $this->api->convertDate(
                explode('.', $this->item['beginn'])
        );
        $this->item['ende'] = $this->api->convertDate(
                explode('.', $this->item['ende'])
        );
        // reise mit der api speichern
        $this->api->save($this->item);

        // nicht mehr nötige daten löschen
        unset($this->item['beginn'],
                $this->item['ende'],
                $this->item['prices']);
    }
}
}
?>

这些是我的错误 - 每个元素中都有来自不同xml记录的数据......我不知道为什么 - 我绝望了......

1st record:
zielgebiet = Alaska
routeid = 24118
titel = Farben von Kanada und Neuengland - ab New York

2nd record:
zielgebiet = AlaskaNeuengland
routeid = 2411824121
titel = Farben von Kanada und Neuengland - ab New YorkFarben von Kanada und Neuengland - ab New York

3rd record:
zielgebiet = AlaskaNeuenglandNordamerika
routeid = 241182412124142
titel = Farben von Kanada und Neuengland - ab New YorkFarben von Kanada und Neuengland - ab New YorkFarben von Kanada und Neuengland - ab Québec

4th record:
zielgebiet = AlaskaNeuenglandNordamerikaNew England
routeid = 24118241212414224206
titel = Farben von Kanada und Neuengland - ab New YorkFarben von Kanada und Neuengland - ab New YorkFarben von Kanada und Neuengland - ab QuébecFarben von Kanada und Neuengland - ab Québec

3 个答案:

答案 0 :(得分:0)

如果你,而不是这个:

$this->item['routeid'] .= $data;

请使用:

$this->item['routeid'] = $data;

答案 1 :(得分:0)

这看起来就是原因,至少从代码块上方的注释来判断:

// assign the $data by the $this->element
switch ($this->element) {
    case "routeid":
        $this->item['routeid'] .= $data;
        break;
    // etc.

使用时:

$this->item['routeid'] .= $data;
                       ^ here

您正在将$data$this->item['routeid']的当前内容联系起来。

你可能只想要:

$this->item['routeid'] = $data;

请注意,这发生在多个地方。

答案 2 :(得分:-1)

你在多个地方都会发生字符串连接,只会在循环中每次都将字符串相互追加。

所以不要...... $this->item['titel'] .= $data;

你只想... $this->item['titel'] = $data;

所以编辑的编辑如下...... 将此块更改为此....

switch ($this->element) {
    case "routeid":
        $this->item['routeid'] = $data;
        break;
    case "name":
        $this->item['titel'] = $data;
        break;
    case "duration":
        $this->item['dauer'] = $data;
        break;
    case "port":
        if ($this->counterRoute != 0 && $this->counterRoute != 1) {
            $this->item['route'][$this->counterRoute-2] = $data;
        }

这个块,对此......

case "bestprice":
        $cabinetype = $this->cabintype;
        $this->item['prices'][$cabinetype][$this->counterPrice] = 
        str_replace(',', '.', $data);
        unset($cabinetype);
        break;
    case "tripbegins":
        $this->item['beginn'] = $data;
        break;
    case "tripends":
        $this->item['ende'] = $data;
        break;
    case "destinationname":
        $this->item['zielgebiet'] = $data;
        break;
    case "shipname":
        $this->item['schiff'] = $data;
        break;