简体   繁体   中英

PHP DOMDocument XML validation - default namespace - element not expected

I try to validate this document in PHP using DOMdocument's schemaValidate:

<?xml version="1.0" encoding="UTF-8"?> <works xmlns="http://pbn.nauka.gov.pl/-/ns/bibliography" pbn-unit-id="1388"><article><title>Mukowiscydoza</title></article></works> 

by using $domDocument->schemaValidate('pbn-report.xsd')

Link to XSD: https://pbn.nauka.gov.pl/help/images/files/pbn-report.xsd.zip

... and I always get an error

Error 1871: Element 'article': This element is not expected. Expected is one of ( { http://pbn.nauka.gov.pl/-/ns/bibliography }article, { http://pbn.nauka.gov.pl/-/ns/bibliography }book, { http://pbn.nauka.gov.pl/-/ns/bibliography }chapter ). on line 0

For me it is incomprehensible. Why do I get an error when I pointed out the default namespace?

Solved.

It turns out that when you create a DOMDocument, when you add an Element every time you need to give Namespace . When generating a document (saveXML) will not make any difference, but if you run schemaValidate, the validator checks DOMDocument object, and not the generated XML.

In other words this code:

$domDocument = new DOMDocument('1.0', "UTF-8");
$domWorks = $domDocument->createElementNS("http://pbn.nauka.gov.pl/-/ns/bibliography",'works');

$domWorksId = $domDocument->createAttribute('pbn-unit-id');
$domWorksId->value = PBNID;
$domWorks->appendChild($domWorksId);

$domDocument->appendChild($domWorks);

$domArticle = $domDocument->createElement('article');
$domArticle->appendChild($domDocument->createElement('title','Mukowiscydoza'));
$domWorks->appendChild($domArticle);

echo htmlentities($domDocument->saveXML());

generates the same XML as this code

$domDocument = new DOMDocument('1.0', "UTF-8");
$domWorks = $domDocument->createElementNS("http://pbn.nauka.gov.pl/-/ns/bibliography",'works');

$domWorksId = $domDocument->createAttribute('pbn-unit-id');
$domWorksId->value = PBNID;
$domWorks->appendChild($domWorksId);

$domDocument->appendChild($domWorks);

$domArticle = $domDocument->createElementNS("http://pbn.nauka.gov.pl/-/ns/bibliography",'article');
$domArticle->appendChild($domDocument->createElementNS("http://pbn.nauka.gov.pl/-/ns/bibliography",'title','Mukowiscydoza'));
$domWorks->appendChild($domArticle);

echo htmlentities($domDocument->saveXML());

But if you check schema

$domDocument->schemaValidate('pbn-report.xsd');

, the first code will return an error. Strange ...

Strange ...

Well not really. As long as the document is in memory, the information about the namespace(s) with the elements is preserved.

In that case the two different methods / parameter here really make a difference even if you don't see a difference in the generated XML (afterwards):

// null namespace
$domArticle = $domDocument->createElement('article');

// vs. concrete namespace
$domArticle = $domDocument->createElementNS(
    'http://pbn.nauka.gov.pl/-/ns/bibliography', 'article'
);

You then serialize the document (what you describe as "generates the same XML" ) as XML and you then load that XML back into memory. Then the elements with no namespace aren't within the null namespace any longer because they inherit their namespace from their parent element.

So you must differ between the document and it's elements in memory (DOM) and in the serialized form (string, file).

You can have similar effects when you do XSLT transformations. So if you experience something strange, it's worth to consider that the document in memory is not representing what you first think even it creates similar - or even exact same - looking XML ;)

尝试将xmlns放在article元素内,然后重试。

xmlns="http://pbn.nauka.gov.pl/-/ns/bibliography"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM