How to validate xml with php
Asked Answered
S

5

12

I have made an api with xml based request for my website.

but sometimes, some customers send me an invalid xml and I want to return a good response.

how can I validate xml?

edited:

Ok, I think I asked wrong question, I want to validate nodes and if some nodes missing then I return best response.

I used to validate this with php and I have to check every nodes. but this way is very hard to modify.

it is my xml example:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<mashhadhost>
    <create>
        <name>example.ir</name>
        <period>60</period>
        <ns>
            <hostAttr>
                <hostName>ns1.example.ir</hostName>
                <hostAddr ip="v4">192.0.2.2</hostAddr>
            </hostAttr>
        </ns>
        <contact type="holder">ex61-irnic</contact>
        <contact type="admin">ex61-irnic</contact>
        <contact type="tech">ex61-irnic</contact>
        <contact type="bill">ex61-irnic</contact>
    </create>
    <auth>
        <code>TOKEN</code>
    </auth>
</mashhadhost>
Stavros answered 19/6, 2013 at 13:0 Comment(4)
you can also try Dealing with XML errorsRotten
You need to provide us: an example of correct XML (i presume the one you posted is valid), your DTD, an example (or more) of WRONG XML and the associated "best response". Otherwise, you won't get much help.Pawsner
@Userpassword: na, it is not even close to my question...Stavros
Googlers: see this answer for a 4-line-small snippet of validating XML without DTD (e.g. Google Merchant)Lantern
U
24

Unfortunately XMLReader didn't validate lots of things in my case.

Here a small piece of class I wrote a while ago:

/**
 * Class XmlValidator
 * @author Francesco Casula <[email protected]>
 */
class XmlValidator
{
    /**
     * @param string $xmlFilename Path to the XML file
     * @param string $version 1.0
     * @param string $encoding utf-8
     * @return bool
     */
    public function isXMLFileValid($xmlFilename, $version = '1.0', $encoding = 'utf-8')
    {
        $xmlContent = file_get_contents($xmlFilename);
        return $this->isXMLContentValid($xmlContent, $version, $encoding);
    }

    /**
     * @param string $xmlContent A well-formed XML string
     * @param string $version 1.0
     * @param string $encoding utf-8
     * @return bool
     */
    public function isXMLContentValid($xmlContent, $version = '1.0', $encoding = 'utf-8')
    {
        if (trim($xmlContent) == '') {
            return false;
        }

        libxml_use_internal_errors(true);

        $doc = new DOMDocument($version, $encoding);
        $doc->loadXML($xmlContent);

        $errors = libxml_get_errors();
        libxml_clear_errors();

        return empty($errors);
    }
}

It works fine with streams and vfsStream as well for testing purposes.

Umbilicus answered 5/5, 2015 at 16:37 Comment(2)
added check to avoid DOMDocument::loadXML(): Empty string supplied as input errorUmbilicus
I don't see how this works with streams. file_get_contents will read whole file in memory and not use streams.Thiel
L
4

If you want to check only if the document is well formed (you don't care about the DTD validity, and don't even have a DTD to validate against) use Domdocument to validate your file, rather than XMLReader, because XMLReader will stream you document and don't load it at once, so isValid() method will only check the first node. You can try a code like this:

 $doc = new \DOMDocument();

 if(@$doc->load($filePath)){
     var_dump("$filePath is a valid XML document");
} else {
      var_dump("$filePath is NOT a valid document");
}
Lofton answered 24/5, 2016 at 19:13 Comment(1)
One should use libxml_use_internal_errors(true) instead of suppressing errors.Lantern
P
2

The PHP documentation has exactly what you need!

XML DOMDocument::validate

I'm sure that you have already defined the proper DTD, right?

<?php
$dom = new DOMDocument;
$dom->Load('book.xml');
if ($dom->validate()) {
    echo "This document is valid!\n";
}
?>
Pawsner answered 19/6, 2013 at 13:3 Comment(2)
or load from string: $dom->loadHTML($string);Premolar
There are legit cases when one won't have a DTDLantern
T
0

You can use XMLReader::isValid().

<?php
    $xml = XMLReader::open('xmlfile.xml');

    // You must to use it
    $xml->setParserProperty(XMLReader::VALIDATE, true);

    var_dump($xml->isValid());
?>
Temperamental answered 19/6, 2013 at 13:3 Comment(1)
Note: This checks the current node, not the entire document.Lofton
L
-2

You can use PHP function:-

$xmlcontents = XMLReader::open('filename.xml');

$xmlcontents->setParserProperty(XMLReader::VALIDATE, true);

var_dump($xmlcontents->isValid());

Source:- http://php.net/manual/en/xmlreader.isvalid.php

Leesaleese answered 19/6, 2013 at 13:4 Comment(2)
Note: This checks the current node, not the entire document.Lofton
Also, the static call XMLReader::open has been deprecatedEgerton

© 2022 - 2024 — McMap. All rights reserved.