Есть ли способ (без установки каких-либо библиотек) проверки XML с помощью пользовательского DTD в PHP?
Проверка XML с помощью настраиваемого DTD в PHP
Ответ 1
Взгляните на PHP DOM, особенно DOMDocument:: schemaValidate и DOMDocument:: validate.
Пример для DOMDocument:: validate довольно прост:
<?php
$dom = new DOMDocument;
$dom->Load('book.xml');
if ($dom->validate()) {
echo "This document is valid!\n";
}
?>
Ответ 2
Если у вас есть 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";
}
Ответ 3
Моя интерпретация исходного вопроса заключается в том, что у нас есть 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.
Ответ 4
Попытка выполнить ответ "owenmarshall":
в xml-validator.php:
добавить html, header, body,...
<?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>