Проверка XML с помощью настраиваемого DTD в PHP

Есть ли способ (без установки каких-либо библиотек) проверки 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.

Попытка завершить «owenmarshall» ответ:

в 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>&lt;/background-color> <br/> <color>&lt;/color> <br/> <font-size>&lt;/font-size> <br/> <header-image>&lt;/header-image> <br/> </template> </template-format>