The program generates an xml file of a similar format.

<?xml version="1.0" encoding="windows-1251"?> <timetable> <teachers options="import:disable,canadd,canremove,canupdate,primarytt,silent" columns="id,name"> <teacher id="*1" name="Ivanov Ivan"/> <teacher id="*2" name="Petrovskii Vasilii"/> <teacher id="*3" name="Sidorova Maria"/> </teachers> <classes options="import:disable,canadd,canremove,canupdate,primarytt,silent" columns="id,name"> <class id="*1" name="11a"/> <class id="*2" name="10b"/> <class id="*3" name="8a"/> </classes> <subjects options="import:disable,canadd,canremove,canupdate,primarytt,silent" columns="id,name"> <subject id="*1" name="Matematika"/> <subject id="*2" name="Fizica"/> <subject id="*3" name="Himia"/> </subjects> <classrooms options="import:disable,canadd,canremove,canupdate,primarytt,silent" columns="id,name"> <classroom id="*1" name="cab 1"/> <classroom id="*2" name="cab 22"/> <classroom id="*3" name="cab 6"/> </classrooms> <cards options="import:disable,canadd,canremove,canupdate,primarytt,silent" columns="day,period,subjectid,teacherids,classroomids"> <card subjectid="*1" teacherids="*1" classroomids="*3" day="2" period="1"/> <card subjectid="*2" teacherids="*3" classroomids="2" day="3" period="4"/> <card subjectid="*3" teacherids="*2" classroomids="*2" day="2" period="3"/> </cards> </timetable> 

How can I parse the last table "cards" in sql, while at the same time that the location of the id, the values ​​of these elements?

Closed due to the fact that off-topic participants 0xdb , aleksandr barakin , freim , LFC , Eugene Krivenja March 12 at 8:53 .

It seems that this question does not correspond to the subject of the site. Those who voted to close it indicated the following reason:

  • " Learning tasks are allowed as questions only on the condition that you tried to solve them yourself before asking a question . Please edit the question and indicate what caused you difficulties in solving the problem. For example, give the code you wrote, trying to solve the problem "- 0xdb, freim, LFC, Eugene Krivenja
If the question can be reformulated according to the rules set out in the certificate , edit it .

  • What exactly is your difficulty? Take simple_xml, open the file, refer to the node. read the children. collect insert request; if I understand your task correctly - teran
  • Yes, you understood correctly, but I am a noob in this area and I needed a rough direction on how to solve it. I will try to read about simple_xml, I hope to turn out. - madblackjack
  • People help to outline the basic structure, knowledge on this issue is nearing zero for me, and from the manuals there is already a square head. - madblackjack
  • Did you read about the basics of using Simple XML ( php.net/manual/ru/simplexml.examples-basic.php )? Did you manage to load this XML and access the nodes? Share your code. - teran

1 answer 1

The first thing you need to do is upload this XML. Everything is simple:

 $xml = simplexml_load_file("data.xml"); 

Next, decide which columns (attributes) you are interested in. Either you already know the set, or you want to use the ones specified in the columns attribute:

 $cols = explode(',', (string)$xml->cards['columns']); // $cols = ['subjectid', 'teacherids']; //если знаете 

Next, the XML card nodes need to be translated into an array view. Let us define for this a function that subtracts only the necessary attributes to us:

 $map = function($card) use ($cols){ $result = []; foreach($cols as $c){ $result[$c] = (string)$card[$c]; } return $result; }; 

You have asterisks in the keys there, we will assume that the attributes are string. Otherwise would result in (int) , for example.

Next, go through the elements and build an array of data:

 $data = []; foreach($xml->cards->card as $card){ $data[] = $map($card); } 

at this stage, we obtain an array of the form

  [0] => Array ( [day] => 2 [period] => 1 [subjectid] => *1 [teacherids] => *1 [classroomids] => *3 ) ........ 

Now you need to connect to the database, use, for example, PDO . You also need SQL query text to insert data. Again, either we know which columns we have and how many values, or not. In the case when we do not know, use something like:

  $sql = "insert into xxx (". implode(',', $cols) . ")\n values (". implode(',', array_fill( 0, count($cols), '?')) . ");"; 

If we know, then we just write a query a la

 $sql = "INSERT INTO xxx (subjectid, teacherids) VALUES (?, ?)"; 

Note that in the general case the column names should be escaped, in the case of mysql these are reverse quotes, for MS SQL, square brackets [] , etc. Or, make sure that the passed rows are valid identifiers of column names and are included in your white list of columns.

At this step, we get the following query text:

 insert into xxx (day,period,subjectid,teacherids,classroomids) values (?,?,?,?,?); 

Now we prepare the request and execute it for each element of the array:

 $pdo = new PDO(...); $st = $pdo->prepare($sql); foreach($data as $d){ $st->execute($d); } 

It is worth noting here that for a relatively large amount of data executing a separate query for each insert is a bad practice. It would be better to break the $data array into parts, 300-500 elements and use the variant of the query to insert several lines at once insert ... values (...), (...), (...) .
Yes, in general, bad in any case, but as part of this issue, let's leave it that way.

But in general, if the XML document is large enough, 50 megabytes will already be enough for Simple XML to come down to download the file. In such cases, SAX parsers are used that do not load the entire document into memory.


addition. missed part about values.

generally speaking, we believe that fields are known to us. Odmeplem functions for downloading directories and map mapping.

 $loadRefs = function($xml, $refs){ $result = []; foreach($refs as $r ){ foreach($xml->$r->children() as $entry){ $id = (string)$entry['id']; $result[$r][$id] = (string)$entry['name']; } } return $result; }; $map = function($card) use ($refs){ return [ 'day' => (int)$card['day'], 'period' => (int) $card['period'], 'subject' => $refs['subjects'][ (string)$card['subjectid'] ], ]; }; 

we cause them and we bring result in base, as well as earlier

 $refs = $loadRefs($xml, ['classes', 'teachers', 'subjects']); $data = []; foreach($xml->cards->card as $card){ $data[] = $map($card); } $pdo = new PDO(...); $sql = "INSERT INTO xxx (`day`, period, subject) VALUES (?,?,?);"; $st = $pdo->prepare($sql); foreach($data as $d){ $st->execute($d); } 
  • Thank you for the detailed scheme, but the question remains with the assignment of values ​​to attributes, i.e. [teacherids] => * 1 should substitute the name "Ivanov Ivan" by ID. The array should be: [0] => Array ([day] => 2 [period] => 1 [subjectid] => Matematika [teacherids] => Ivanov Ivan [classroomids] => cab 6) - madblackjack
  • @madblackjack added the answer, but this is not a normal form for the database. - teran
  • @ teran sorry for the annoying. Where does VALUES take values? Because the form (?,?,?) Does not send anything to the mysql database. - madblackjack
  • Please help $ function loadRefs not working, I can not find the cause - madblackjack pm