Is it possible to validate XML on multiple schemas in PHP?

I am wondering if it is possible to check xml for multiple schemas in PHP, or do I need to somehow merge my schemas.

Thanks for the answer!

+4
source share
4 answers

I solved my problem with a simple PHP script:

$mainSchemaFile = dirname(__FILE__) . "/main-schema.xml"; $additionalSchemaFile = 'second-schema.xml'; $additionalSchema = simplexml_load_file($additionalSchemaFile); $additionalSchema->registerXPathNamespace("xs", "http://www.w3.org/2001/XMLSchema"); $nodes = $additionalSchema->xpath('/xs:schema/*'); $xml = ''; foreach ($nodes as $child) { $xml .= $child->asXML() . "\n"; } $result = str_replace("</xs:schema>", $xml . "</xs:schema>", file_get_contents($mainSchemaFile)); var_dump($result); // merged schema in form XML (string) 

But this is possible only because the schemes are the same - i.e.

 <xs:schema xmlns="NAMESPACE" targetNamespace="NAMESPACE" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> 

located in both files.

+1
source

The main schema file must contain an include tag for each child schema file. For instance:

 <xs:include schemaLocation="2nd_schema_file.xsd"/> 
+3
source

Syfmony2 developers have solved this problem. It is not freakin 'clean, but will do:

 function validateSchema(\DOMDocument $dom) { $tmpfiles = array(); $imports = ''; foreach ($this->schemaLocations as $namespace => $location) { $parts = explode('/', $location); if (preg_match('#^phar://#i', $location)) { $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); if ($tmpfile) { file_put_contents($tmpfile, file_get_contents($location)); $tmpfiles[] = $tmpfile; $parts = explode('/', str_replace('\\', '/', $tmpfile)); } } $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts)); $imports .= sprintf(' <xsd:import namespace="%s" schemaLocation="%s" />' . PHP_EOL, $namespace, $location); } $source = <<<EOF <?xml version="1.0" encoding="utf-8" ?> <xsd:schema xmlns="http://symfony.com/schema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://symfony.com/schema" elementFormDefault="qualified"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/> $imports </xsd:schema> EOF ; $current = libxml_use_internal_errors(true); $valid = $dom->schemaValidateSource($source); foreach ($tmpfiles as $tmpfile) { @unlink($tmpfile); } if (!$valid) { throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors())); } libxml_use_internal_errors($current); } 
+1
source

Given that the DOMDocument::schemaValidate gets the path to the schema file as a parameter, d say that you just need to call this method several times: once for each of your schemas.

See also DOMDocument::schemaValidateSource if you have your schemas in PHP strings; the idea (and the answer) will be the same: just call the method several times.

-1
source

Source: https://habr.com/ru/post/1308481/


All Articles