Программа формирует xml файл, подобного формата.
<?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>
Каким образом можно спарсить последнюю таблицу "cards" в sql, при этом чтобы место ид, были значения этих элементов?
Первое, что вам надо необходимо сделать - загрузить этот XML. Тут все просто:
$xml = simplexml_load_file("data.xml");
Далее определиться какие столбцы (атрибуты) вас интересуют. Либо вы уже знаете набор, либо вы хотите использовать те, что указаны в атрибуте columns
:
$cols = explode(',', (string)$xml->cards['columns']);
// $cols = ['subjectid', 'teacherids']; //если знаете
Далее XML узлы card
нужно перевести в вид массива. Определим для этого функцию, которая вычленит нам только нужные атрибуты:
$map = function($card) use ($cols){
$result = [];
foreach($cols as $c){
$result[$c] = (string)$card[$c];
}
return $result;
};
У вас там в ключах звездочки присутствуют, будем считать, что атрибуты строковые. Иначе приводили бы к (int)
, например.
Далее пройдемся по элементам и построим массив данных:
$data = [];
foreach($xml->cards->card as $card){
$data[] = $map($card);
}
на данном этапе получим массив вида
[0] => Array (
[day] => 2
[period] => 1
[subjectid] => *1
[teacherids] => *1
[classroomids] => *3
)
........
Теперь необходимо подключиться к БД, используйте, например PDO
. Также нужен текст SQL запроса для вставки данных. Опять же, либо мы знаем какие у нас столбцы и сколько значений, либо нет. В случае, когда не знаем, используем нечто вида:
$sql = "insert into xxx (".
implode(',', $cols) .
")\n values (".
implode(',', array_fill( 0, count($cols), '?')) .
");";
Если же знаем, то просто пишем запрос а-ля
$sql = "INSERT INTO xxx (subjectid, teacherids) VALUES (?, ?)";
Обратите внимание, что в общем случае наименования столбцов должны быть экранированы, в случае mysql это обратные кавычки, для MS SQL - квадратные скобки []
, и т.д. Либо убедиьтся, что переданные строки - валидные идентификаторы названий столбцов и входят в ваш "белый список" столбцов.
На этом шаге получаем следующий текст запроса:
insert into xxx (day,period,subjectid,teacherids,classroomids)
values (?,?,?,?,?);
Теперь подготавливаем запрос, и выполняем его для каждого элемента массива:
$pdo = new PDO(...);
$st = $pdo->prepare($sql);
foreach($data as $d){
$st->execute($d);
}
Здесь стоит отметить, что для относительно большого объема данных выполнения отдельного запроса на каждую вставку - плохая практика. Лучше будет разбить массив $data
на части, элементов по 300-500 и использовать вариант запроса на вставку сразу нескольких строк insert ... values (...), (...), (...)
.
Да в целом плохо в любом случае, но в рамках данного вопроса оставим так.
Ну а в целом, если XML документ достаточно большой, мегабайт 50 уже будет достаточно, чтобы Simple XML уже слег на загрузке файла. В подобных случаях используют SAX-парсеры, которые не загружают весь документ в память.
дополнение. пропустил часть про значения.
в общем говоря, считаем что поля список полей нам известен. Опредялем функции для загрузки справочников и маппинга карточек.
$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'] ],
];
};
вызываем их и вносим результат в базу, как и ранее
$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);
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Есть код для подключения стилей и скриптов из header в footer для оптимизации
Как можно узнать способы оплаты для клиентов, в определенном городе,как здесь
есть скрипт, который необходимо останавливать по клику кнопки отмены