PHP simpleXML пытается обработать довольно сложный файл - PullRequest
1 голос
/ 15 апреля 2011

Я борюсь здесь, потратил большую часть сегодняшнего дня, пытаясь разобрать XML-документ автоматического генерирования, экспортированный из отчетов Crystal, XML не очень хорош, поэтому, пожалуйста, держитесь за меня.

Файл, с которым я должен работать, имеет следующую структуру:

<?xml version="1.0" encoding="UTF-8" ?>
<FormattedReport xmlns = 'urn:crystal-reports:schemas' xmlns:xsi = 'http://www.w3.org/2000/10/XMLSchema-instance'>
    <FormattedAreaPair Level="0" Type="Report">
    <FormattedAreaPair Level="1" Type="Details">
    <FormattedArea Type="Details">
        <FormattedSections>
        <FormattedSection SectionNumber="0">
        <FormattedReportObjects>
        FormattedReportObject xsi:type="CTFormattedField" Type="xsd:long" FieldName="{tblCon.ManifestNR}"><ObjectName>ManifestNR1</ObjectName>
        <FormattedValue>1,907</FormattedValue>
        <Value>1907.00</Value>
        </FormattedReportObject>
        <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:timeInstant" FieldName="{tblCon.ShippingDate}"><ObjectName>ShippingDate1</ObjectName>
        <FormattedValue>14/04/2011</FormattedValue>
        <Value>2011-04-14T00:00:00</Value>
        </FormattedReportObject>
        ... so on and so forth ...
        </FormattedReportObjects>
        </FormattedSection>
        </FormattedSections>
        </FormattedArea>
        </FormattedAreaPair>
    <FormattedReportObjects>
        FormattedReportObject xsi:type="CTFormattedField" Type="xsd:long" FieldName="{tblCon.ManifestNR}"><ObjectName>ManifestNR1</ObjectName>
        <FormattedValue>1,907</FormattedValue>
        <Value>1907.00</Value>
        </FormattedReportObject>
        <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:timeInstant" FieldName="{tblCon.ShippingDate}"><ObjectName>ShippingDate1</ObjectName>
        <FormattedValue>14/04/2011</FormattedValue>
        <Value>2011-04-14T00:00:00</Value>
        </FormattedReportObject>
        ... so on and so forth ...
        </FormattedReportObjects>
        </FormattedSection>
        </FormattedSections>
        </FormattedArea>
        </FormattedAreaPair>
 <FormattedAreaPair Level="1" Type="Details">
    <FormattedArea Type="Details">
        <FormattedSections>
        <FormattedSection SectionNumber="0">
        <FormattedReportObjects>
        FormattedReportObject xsi:type="CTFormattedField" Type="xsd:long" FieldName="{tblCon.ManifestNR}"><ObjectName>ManifestNR1</ObjectName>
        <FormattedValue>1,907</FormattedValue>
        <Value>1907.00</Value>
        </FormattedReportObject>
        <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:timeInstant" FieldName="{tblCon.ShippingDate}"><ObjectName>ShippingDate1</ObjectName>
        <FormattedValue>14/04/2011</FormattedValue>
        <Value>2011-04-14T00:00:00</Value>
        </FormattedReportObject>
        ... so on and so forth ...
        </FormattedReportObjects>
        </FormattedSection>
        </FormattedSections>
        </FormattedArea>
        </FormattedAreaPair>
    <FormattedReportObjects>
        FormattedReportObject xsi:type="CTFormattedField" Type="xsd:long" FieldName="{tblCon.ManifestNR}"><ObjectName>ManifestNR1</ObjectName>
        <FormattedValue>1,907</FormattedValue>
        <Value>1907.00</Value>
        </FormattedReportObject>
        <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:timeInstant" FieldName="{tblCon.ShippingDate}"><ObjectName>ShippingDate1</ObjectName>
        <FormattedValue>14/04/2011</FormattedValue>
        <Value>2011-04-14T00:00:00</Value>
        </FormattedReportObject>
        ... so on and so forth ...
        </FormattedReportObjects>
        </FormattedSection>
        </FormattedSections>
        </FormattedArea>
        </FormattedAreaPair>
        </FormattedAreaPair>
        </FormattedReport>

Итак, я пытаюсь вызвать функцию PHP, которая будет анализировать XML и в конечном итоге сохранять его в базе данных SQL.

например:

ManifestNR: 1903 Дата Доставки: 12/04/2011 CarrierID: TNT03 TrackingRef: 234234232 ... и т.д. для каждой записи ...

поэтому я попытался сделать это с помощью DOM, а затем наткнулся на simpleXML, я прочитал несколько статей и искал здесь реализации, но я просто не могу получить доступ к данным в конечных узлах (или любых других). другие данные). Является ли simpleXML «нет-нет» с такими структурами?

Последний PHP, который я использую:

<?php

if (file_exists('tracking.xml')) {
    $xml = simplexml_load_file('tracking.xml');

  //  print_r($xml);

   foreach( $xml as $FormattedReport->FormattedAreaPair->FormattedAreaPair ) 
        {
        foreach($FormattedReport as $node->FormattedArea->FormattedSections->FormattedSection->FormattedReportObjects)
        echo $node->FormattedReportObject->Value;
        }

} else {
    exit('Failed to open xml');
}
?>

Я пытался разобраться с основами, но все равно не повезло. Не отражает результат.

Спасибо за ваше время, ребята!

решаемые

Любой, кто находится в подобных обстоятельствах, имеет немного направления.

  1. игнорировать корневой узел, это ваша переменная $ по умолчанию при импорте строки / файла XML
  2. Если у вас есть вложенные группы, сначала создайте узел для родителя, например, $ xml-> FormattedAreaPair-> FormattedAreaPair как $ parentnode
  3. Использование вашего родительского узла в цикле через все дочерние элементы
  4. Если у вас есть поле атрибута, обращайтесь к нему следующим образом: (строка) $ node ['FieldName'])
  5. Сравните полученный атрибут со строкой, а затем обработайте результат.
  6. Хватит тянуть за волосы.

(простите за ужасное форматирование кода)

<?php

if (file_exists('tracking.xml')) { 
    $xml = simplexml_load_file('tracking.xml');

    //print_r($xml); 
    foreach( $xml->FormattedAreaPair->FormattedAreaPair as $parentnode ) { 
        foreach($parentnode->FormattedArea->FormattedSections->FormattedSection->FormattedReportObjects->FormattedReportObject as $node){ 
            //echo "FormattedValue: ".$node->FormattedValue."<br />"; 
            switch((string) $node['FieldName']){ 
                case '{tblCon.ManifestNR}': 
                    echo 'Manifest: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{tblCon.ShippingDate}': 
                    echo 'Shipping Date: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{tblCon.CarrierID}': 
                    echo 'Carrier ID: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{tblCon.CustConRefTX}': 
                    echo 'Customer Reference: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{tblCon.ServiceCodeTX}': 
                    echo 'Service Code: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{tblCon.TotalWeightNR}': 
                    echo 'Total Weight: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{tblCon.ValueNR}': 
                    echo 'Value: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{tblCon.TotalVolumeNR}': 
                    echo 'Total Volume: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{tblCon.GoodsDesc}': 
                    echo 'Goods Description: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{tblConAddr.ReceiverNameTX}': 
                    echo 'Receiver Name: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{@SalesOrder}': 
                    echo 'Sales Order: '.$node->FormattedValue."<br />"; 
                    break; 
                case '{@TrackingReference}': 
                    echo 'Tracking Reference: '.$node->FormattedValue."<br />"; 
                    break;
            }
        }
    echo "---------------------------- <br />";
    }
} 
else { 
    exit('Failed to open xml'); 
}

?>

Ответы [ 3 ]

3 голосов
/ 15 апреля 2011

Примеров в Руководстве должно быть достаточно (в частности, Пример № 4). Ты выглядишь как достаточно умный парень. Проблема в том, что вы делаете неправильно .

example.php

<?php
$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<movies>
 <movie>
  <title>PHP: Behind the Parser</title>
  <characters>
   <character>
    <name>Ms. Coder</name>
    <actor>Onlivia Actora</actor>
   </character>
   <character>
    <name>Mr. Coder</name>
    <actor>El Act&#211;r</actor>
   </character>
  </characters>
  <plot>
   So, this language. It's like, a programming language. Or is it a
   scripting language? All is revealed in this thrilling horror spoof
   of a documentary.
  </plot>
  <great-lines>
   <line>PHP solves all my web problems</line>
  </great-lines>
  <rating type="thumbs">7</rating>
  <rating type="stars">5</rating>
 </movie>
</movies>
XML;
?>

Пример # 4

<?php
include 'example.php';

$xml = new SimpleXMLElement($xmlstr);

/* For each <character> node, we echo a separate <name>. */
foreach ($xml->movie->characters->character as $character) {
   echo $character->name, ' played by ', $character->actor, PHP_EOL;
}

?>

Обратите внимание, что при использовании конструкции foreach необходимо указать путь к узлам определенного типа. Второй элемент в foreach - это просто (пустая) переменная, которую вы используете для хранения текущего узла в итерации.

1 голос
/ 16 февраля 2012

Как получить доступ к таким атрибутам, как i: nil, с помощью simplexml (экземпляр XMLSchema):

Xml:

<item i:nil="true"/>

Php:

(bool) $item->attributes('i',true)->nil;
0 голосов
/ 12 января 2012

Файл, с которым я имел дело, был ~ 1 ГБ, поэтому я не мог загрузить файл xml одновременно.Вот контроллер CI, который я сделал для разбора Crystal Reports XML.

<?php

class Parse_crystal_reports_xml extends CI_Controller {

    function index(){
        $base_path = "/path/to/xml/";
        $xml_file = "xml_file.xml";
        $file_header = '<?xml version="1.0" encoding="UTF-8" ?>';
        $separator = '<FormattedAreaPair Level="1" Type="Details">';
        $xml_data = explode($separator, str_replace($file_header, '', file_get_contents($base_path.$xml_file)));
        $bad_names = array('xsi:','xsd:');
        foreach($xml_data as $block_num => $block) : 
            if(!$block_num) : continue; endif;
            $fields = new SimpleXMLElement(str_replace($bad_names, '', $file_header."\n".$separator.$block));
            $temp_array = array();
            foreach($fields->FormattedArea->FormattedSections->FormattedSection->FormattedReportObjects->FormattedReportObject as $field_num => $field) :
                // print_r($field);
                $temp_array[$this->make_slug($field['FieldName'])] = $this->clean_word((string)$field->FormattedValue);
            endforeach;
            // print_r($fields);
            print_r($temp_array);
            die;
        endforeach;
    }

    function make_slug($string){
        return strtolower(trim(preg_replace('/\W+/', '_', $string), '_'));
    }

    function clean_word($string){
        return trim(preg_replace('/\s+/', ' ', $string));
    }
}
?>
...