23

how to validate a xml file against a xsd? there is domdocument::schemaValidate() but It does not tell where are the errors. is there any class for that? does it have any worth making that parser from scratch? or is it just reinventing he wheel,

3 Answers 3

29

This code does the business:

$xml= new DOMDocument();
$xml->loadXML(<A string goes here containing the XML data>, LIBXML_NOBLANKS); // Or load if filename required
if (!$xml->schemaValidate(<file name for the XSD file>)) // Or schemaValidateSource if string used.
{
   // You have an error in the XML file
}

See the code in http://php.net/manual/en/domdocument.schemavalidate.php To retrieve the errors.

I.e.

justin at redwiredesign dot com 08-Nov-2006 03:32 post.

2
  • i don't think it tells where the errors are and where does it failing and why it is failing .does it?
    – varuog
    Commented Jul 25, 2012 at 13:15
  • Unfortunately the PHP version makes use of libxml2 which does not support the XSD of the XSLT 2.0 specification... Commented Dec 29, 2013 at 1:12
13

User contrib from http://php.net/manual/en/domdocument.schemavalidate.php

It works like a charm!

For more detailed feedback from DOMDocument::schemaValidate, disable libxml errors and fetch error information yourself. See http://php.net/manual/en/ref.libxml.php for more info.

example.xml

<?xml version="1.0"?>
<example>
    <child_string>This is an example.</child_string>
    <child_integer>Error condition.</child_integer>
</example>

example.xsd

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
    <xs:element name="example">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="child_string" type="xs:string"/>
                <xs:element name="child_integer" type="xs:integer"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

PHP

<?php

function libxml_display_error($error)
{
    $return = "<br/>\n";
    switch ($error->level) {
        case LIBXML_ERR_WARNING:
            $return .= "<b>Warning $error->code</b>: ";
            break;
        case LIBXML_ERR_ERROR:
            $return .= "<b>Error $error->code</b>: ";
            break;
        case LIBXML_ERR_FATAL:
            $return .= "<b>Fatal Error $error->code</b>: ";
            break;
    }
    $return .= trim($error->message);
    if ($error->file) {
        $return .=    " in <b>$error->file</b>";
    }
    $return .= " on line <b>$error->line</b>\n";

    return $return;
}

function libxml_display_errors() {
    $errors = libxml_get_errors();
    foreach ($errors as $error) {
        print libxml_display_error($error);
    }
    libxml_clear_errors();
}

// Enable user error handling
libxml_use_internal_errors(true);

$xml = new DOMDocument();
$xml->load('example.xml');

if (!$xml->schemaValidate('example.xsd')) {
    print '<b>DOMDocument::schemaValidate() Generated Errors!</b>';
    libxml_display_errors();
}

?>
3
  • It looks like the code on ibm.com/developerworks/library/x-validxphp.
    – Drasill
    Commented Dec 8, 2015 at 20:36
  • Sorry to post years later, but how could you change the code above to validate against a schema file (xsd) with dependencies on other schema files (xsd)?
    – Totoro53
    Commented Nov 30, 2017 at 14:39
  • 1
    Again years later ;) If you use schemaValidate it will resolve dependencies, if you use schemaValidateSource it wouldn't. In case you experience problems you might need to check the relative paths of the dependencies.
    – bln_dev
    Commented Sep 24, 2019 at 11:11
2

This is a complete code snippet for displaying xsd validation errors:

    $xml = '<test/>';
    $xsd = '/path/to/xsd';
    // needed for getting errors
    libxml_use_internal_errors(true);

    $domDocument= new DOMDocument();
    $domDocument->loadXML($xml); 
    if (!$domDocument->schemaValidate($xsd)) {
        $errors = libxml_get_errors();
        foreach ($errors as $error) {
            print_r($error);
        }
        libxml_clear_errors();
    }

Not the answer you're looking for? Browse other questions tagged or ask your own question.