在 PHP 中使用自定义 DTD 验证 XML
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/101935/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Validate XML using a custom DTD in PHP
提问by michael
Is there a way (without installing any libraries) of validating XML using a custom DTD in PHP?
有没有办法(不安装任何库)在 PHP 中使用自定义 DTD 验证 XML?
采纳答案by owenmarshall
Take a look at PHP's DOM, especially DOMDocument::schemaValidateand DOMDocument::validate.
看看PHP 的 DOM,尤其是DOMDocument::schemaValidate和DOMDocument::validate。
The example for DOMDocument::validate is fairly simple:
DOMDocument::validate 的例子相当简单:
<?php
$dom = new DOMDocument;
$dom->Load('book.xml');
if ($dom->validate()) {
echo "This document is valid!\n";
}
?>
回答by S?ren Jacobi
If you have the dtd in a string, you can validate against it by using a data wrapperfor the dtd:
如果字符串中有 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";
}
回答by Peter
My interpretation of the original question is that we have an "on board" XML file that we want to validate against an "on board" DTD file. So here's how I would implement the "interpolate a local DTD inside the DOCTYPE element" idea expressed in comments by both Soren and PayamRWD:
我对原始问题的解释是,我们有一个“机载”XML 文件,我们希望根据“机载”DTD 文件对其进行验证。所以这里是我将如何实现 Soren 和 PayamRWD 的评论中表达的“在 DOCTYPE 元素中插入本地 DTD”的想法:
public function validate($xml_realpath, $dtd_realpath=null) {
$xml_lines = file($xml_realpath);
$doc = new DOMDocument;
if ($dtd_realpath) {
// Inject DTD inside DOCTYPE line:
$dtd_lines = file($dtd_realpath);
$new_lines = array();
foreach ($xml_lines as $x) {
// Assume DOCTYPE SYSTEM "blah blah" format:
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));
}
// Enable user error handling
libxml_use_internal_errors(true);
if (@$doc->validate()) {
echo "Valid!\n";
} else {
echo "Not valid:\n";
$errors = libxml_get_errors();
foreach ($errors as $error) {
print_r($error, true);
}
}
}
Note that error handling has been suppressed for brevity, and there may be a better/more general way to handle the interpolation. But I haveactually used this code with real data, and it works with PHP version 5.2.17.
请注意,为简洁起见,错误处理已被抑制,并且可能有更好/更通用的方法来处理插值。但是,我已经实际使用此代码与真实的数据,并将其与PHP版本5.2.17工作。
回答by PayamRWD
Trying to complete "owenmarshall" answer:
试图完成“owenmarshall”的回答:
in xml-validator.php:
在 xml-validator.php 中:
add html, header, body, ...
添加 html、标题、正文、...
<?php
$dom = new DOMDocument; <br/>
$dom->Load('template-format.xml');<br/>
if ($dom->validate()) { <br/>
echo "This document is valid!\n"; <br/>
}
?>
template-format.xml:
模板格式.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>

