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

发布于 2024-07-05 20:42:09 字数 47 浏览 7 评论 0原文

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

Is there a way (without installing any libraries) of validating XML using a custom DTD in PHP?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

追星践月 2024-07-12 20:42:09

我对最初问题的解释是,我们有一个“板载”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);
        }
    }
}

请注意,为了简洁起见,错误处理已被抑制,并且可能有更好/更通用的方法来处理插值。 但我实际上已将这段代码与真实数据一起使用,并且它适用于 PHP 版本 5.2.17。

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:


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.

中性美 2024-07-12 20:42:09

看看 PHP 的 DOM,尤其是 DOMDocument::schemaValidateDOMDocument::validate.

DOMDocument::validate 的示例相当简单:

<?php
$dom = new DOMDocument;
$dom->Load('book.xml');
if ($dom->validate()) {
    echo "This document is valid!\n";
}
?>

Take a look at PHP's DOM, especially DOMDocument::schemaValidate and DOMDocument::validate.

The example for DOMDocument::validate is fairly simple:

<?php
$dom = new DOMDocument;
$dom->Load('book.xml');
if ($dom->validate()) {
    echo "This document is valid!\n";
}
?>
小伙你站住 2024-07-12 20:42:09

如果字符串中有 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";
}

If you have the dtd in a string, you can validate against it by using a data wrapper for the 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";
}
绮烟 2024-07-12 20:42:09

尝试完成“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/>
}

?>

template-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>

Trying to complete "owenmarshall" answer:

in xml-validator.php:

add 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/>
}

?>

template-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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文