Есть ли способ (без установки каких-либо библиотек) проверки XML с помощью пользовательского DTD в PHP?
Взгляните на DOM PHP , особенно DOMDocument :: schemaValidate и DOMDocument :: validate .
Пример для DOMDocument :: validate довольно прост:
<?php $dom = new DOMDocument; $dom->Load('book.xml'); if ($dom->validate()) { echo "This document is valid!\n"; } ?>
Если у вас есть dtd в строке, вы можете проверить его, используя обертку данных для dtd:
$xml = '<?xml version="1.0"?> <!DOCTYPE note SYSTEM "note.dtd"> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don\'t forget me this weekend!</body> </note>'; $dtd = '<!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)>'; $root = 'note'; $systemId = 'data://text/plain;base64,'.base64_encode($dtd); $old = new DOMDocument; $old->loadXML($xml); $creator = new DOMImplementation; $doctype = $creator->createDocumentType($root, null, $systemId); $new = $creator->createDocument(null, null, $doctype); $new->encoding = "utf-8"; $oldNode = $old->getElementsByTagName($root)->item(0); $newNode = $new->importNode($oldNode, true); $new->appendChild($newNode); if (@$new->validate()) { echo "Valid"; } else { echo "Not valid"; }
Моя интерпретация исходного вопроса заключается в том, что у нас есть XML-файл на борту, который мы хотим проверить на основе DTD-файла на борту. Итак, вот как я буду реализовывать «интерполяцию локального DTD внутри элемента DOCTYPE», выраженную в комментариях как Soren, так и PayamRWD:
public function validate ($ xml_realpath, $ dtd_realpath = null) { $ xml_lines = файл ($ xml_realpath); $ doc = новый DOMDocument; if ($ dtd_realpath) { // Ввод DTD внутри строки DOCTYPE: $ dtd_lines = файл ($ dtd_realpath); $ new_lines = array (); foreach ($ xml_lines as $ x) { // Предположим формат DOCTYPE SYSTEM "blah blah": if (preg_match ('/ DOCTYPE /', $ x)) { $ y = preg_replace ('/ SYSTEM "(. *)" /', "[\ n". implode ("\ n", $ dtd_lines). "\ n]", $ x); $ new_lines [] = $ y; } else { $ new_lines [] = $ x; } } $ doc-> loadXML (implode ("\ n", $ new_lines)); } else { $ doc-> loadXML (implode ("\ n", $ xml_lines)); } // Включить обработку ошибок пользователя libxml_use_internal_errors (истина); if (@ $ doc-> validate ()) { echo "Valid! \ n"; } else { echo "Недействительно: \ n"; $ errors = libxml_get_errors (); foreach ($ errors as $ error) { print_r ($ error, true); } } }
Обратите внимание, что обработка ошибок была подавлена для краткости, и может быть лучший / более общий способ обработки интерполяции. Но я действительно использовал этот код с реальными данными, и он работает с PHP версии 5.2.17.
в xml-validator.php:
добавить html, заголовок, тело, …
<?php $dom = new DOMDocument; <br/> $dom->Load('template-format.xml');<br/> if ($dom->validate()) { <br/> echo "This document is valid!\n"; <br/> } ?>
Шаблон-format.xml:
<?xml version="1.0" encoding="utf-8"?> <!-- DTD to Validate against (format example) --> <!DOCTYPE template-format [ <br/> <!ELEMENT template-format (template)> <br/> <!ELEMENT template (background-color, color, font-size, header-image)> <br/> <!ELEMENT background-color (#PCDATA)> <br/> <!ELEMENT color (#PCDATA)> <br/> <!ELEMENT font-size (#PCDATA)> <br/> <!ELEMENT header-image (#PCDATA)> <br/> ]> <!-- XML example --> <template-format> <template> <background-color></background-color> <br/> <color></color> <br/> <font-size></font-size> <br/> <header-image></header-image> <br/> </template> </template-format>