简体   繁体   English

使用PHP中的自定义DTD验证XML

[英]Validate XML using a custom DTD in PHP

是否有一种方法(没有安装任何库)使用PHP中的自定义DTD验证XML?

Take a look at PHP's DOM , especially DOMDocument::schemaValidate and DOMDocument::validate . 看一下PHP的DOM ,特别是DOMDocument :: schemaValidateDOMDocument :: 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";
}
?>

If you have the dtd in a string, you can validate against it by using a data wrapper for 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";
}

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. 我对原始问题的解释是,我们有一个“板载”XML文件,我们想要根据“板载”DTD文件进行验证。 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: 因此,我将如何实现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 have actually used this code with real data, and it works with PHP version 5.2.17. 但我实际上将此代码与真实数据一起使用,并且它适用于PHP 5.2.7版。

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: 模板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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM