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>
Pooya
  • 1,508
  • 3
  • 17
  • 38
  • you can also try [Dealing with XML errors](http://php.net/manual/en/simplexml.examples-errors.php) – Laz Karimov Jun 19 '13 at 13:04
  • 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. – STT LCU Jun 19 '13 at 13:19
  • @Userpassword: na, it is not even close to my question... – Pooya Mar 18 '14 at 12:45
  • 1
    Googlers: [see this answer](https://stackoverflow.com/questions/4554233/how-check-if-a-string-is-a-valid-xml-with-out-displaying-a-warning-in-php/52332194#52332194) for a 4-line-small snippet of validating XML without DTD (e.g. Google Merchant) – ᴍᴇʜᴏᴠ Sep 14 '18 at 12:41

5 Answers5

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 <fra.casula@gmail.com>
 */
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.

Francesco Casula
  • 26,184
  • 15
  • 132
  • 131
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");
}
Amaynut
  • 4,091
  • 6
  • 39
  • 44
  • 1
    One should use [`libxml_use_internal_errors(true)`](http://php.net/manual/en/function.libxml-use-internal-errors.php) instead of suppressing errors. – ᴍᴇʜᴏᴠ Sep 14 '18 at 12:43
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";
}
?>
STT LCU
  • 4,348
  • 4
  • 29
  • 47
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());
?>
Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
-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

Vivek Sadh
  • 4,230
  • 3
  • 32
  • 49