PHP özel bir DTD kullanarak XML doğrulamak

4 Cevap php

PHP özel bir DTD kullanarak XML doğrulama (herhangi bir kütüphane yüklemeden) bir yolu var mı?

4 Cevap

PHP's DOM bir göz atın özellikle DOMDocument::schemaValidate ve DOMDocument::validate.

DOMDocument :: validate için örnek oldukça basittir:

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

Eğer bir dize DTD varsa, DTD için bir data wrapper ile karşı doğrulamak:

$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";
}

Orijinal soruya Benim yorumum biz bir "gemide" DTD dosyasında karşı doğrulamak için istediğiniz bir "gemide" XML dosyası olması. Yani burada ben Soren ve PayamRWD hem yorumlarına ifade "DOCTYPE öğesi içinde yerel bir DTD sokmak" fikrini uygulamak nasıl:

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);
        }
    }
}

Bu hata işleme kısalık için bastırılmış olan ve interpolasyon işlemek için daha iyi / daha genel bir yolu olabilir unutmayın. Ama ben have aslında gerçek veriler ile bu kodu kullanılan ve PHP sürümü 5.2.17 ile çalışır.

Trying to complete "owenmarshall" answer:

------------- Xml-validator.php IN: --------------

html, başlık, gövde, eklemek ...

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

>

------------- Şablon-format.xml: --------------

<?xml version="1.0" encoding="utf-8">

<- (Formatı örneğin) karşı doğrulamak için DTD ->

<!DOCTYPE template-format [
<!ELEMENT template-format (template)>
<!ELEMENT template (background-color, color, font-size, header-image)>
<!ELEMENT background-color (#PCDATA)>
<!ELEMENT color (#PCDATA)>
<!ELEMENT font-size (#PCDATA)>
<!ELEMENT header-image (#PCDATA)>
]>

<- XML ​​örneği ->