rap-2-h
rap-2-h

Reputation: 31948

XSD Validation error on xml:lang

I try to validate this (XSD : http://www.imsglobal.org/xsd/imsrdceo_rootv1p0.xsd) :

<?xml version="1.0" encoding="utf-8"?>
<rdceo xmlns="http://www.imsglobal.org/xsd/imsrdceo_rootv1p0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsrdceo_rootv1p0 http://www.imsglobal.org/xsd/imsrdceo_rootv1p0.xsd http://www.w3.org/XML/1998/namespace http://www.w3.org/2001/xml.xsd">
    <identifier>5040d336776eb</identifier>
    <title>
        <langstring xml:lang="en">titre</langstring>
    </title>
</rdceo>

But it says (on various sites and with my PHP code):

The attribute 'xml:lang' is not allowed

Here is my PHP code.

<?php

class RDCEOObjectiveBuilder {

    public  $id,
            $title,
            $description;

    public function build() {
        $dom = new DOMDocument('1.0', 'utf-8');

        $root = $dom->createElementNS(
            'http://www.imsglobal.org/xsd/imsrdceo_rootv1p0',
            'rdceo'
        );
        $root->setAttributeNS(
            'http://www.w3.org/2000/xmlns/' ,
            'xmlns:xsi',
            'http://www.w3.org/2001/XMLSchema-instance'
        );
        $root->setAttributeNS(
            'http://www.w3.org/2001/XMLSchema-instance',
            'xsi:schemaLocation',
            'http://www.imsglobal.org/xsd/imsrdceo_rootv1p0 http://www.imsglobal.org/xsd/imsrdceo_rootv1p0.xsd http://www.w3.org/XML/1998/namespace http://www.w3.org/2001/xml.xsd'
        );

        $id = $dom->createElementNS('http://www.imsglobal.org/xsd/imsrdceo_rootv1p0', 'identifier', $this->id);

        $title = $dom->createElementNS('http://www.imsglobal.org/xsd/imsrdceo_rootv1p0', 'title');
        $title_lang = $dom->createElementNS('http://www.imsglobal.org/xsd/imsrdceo_rootv1p0', 'langstring', $this->title);
        $title_lang->appendChild(new DOMAttr('xml:lang', 'en'));
        $title->appendChild($title_lang);

        $root->appendChild($id);
        $root->appendChild($title);
        $dom->appendChild($root);

        $dom->schemaValidate('imsrdceo_rootv1p0.xsd');
        $dom->formatOutput = true;
        return $dom->saveXML();
    }
}

$test = new RDCEOObjectiveBuilder();
$test->id = uniqid();
$test->title = 'titre';
echo $test->build();
?>

I don't understand why xml:lang is not allowed... In every examples on http://www.imsglobal.org/competencies/ (the ones who created the xsd), they uses xml:lang

Example : http://www.imsglobal.org/competencies/Examples/MadeUp_Examplev1.xml

Can you tell me why ? Thanks a lot !

Upvotes: 3

Views: 1331

Answers (2)

Petru Gardea
Petru Gardea

Reputation: 21638

The key thing here is the use of the xs:anyAttribute on the langstring element, it's processing clause which is strict, and how xml:lang is supposed to work.

strict means the XML processor must obtain the schema for the required namespaces and validate any attribute from those namespaces.

The thing, any decent XML Schema processor is supposed to have built in support for what I call fundamental schemas; xml.xsd, which describes xml:lang, is just one of them.

In my case, using QTAssistant, your XML validates just fine.

I can tell you that it would've helped other processors if they (the schema authors) would've included an xsd:import to the http://www.w3.org/XML/1998/namespace, even without a schema location, and maybe even explicitly ref the xml:land attribute for content which is subject to i18n.

But they didn't... What you can do now is to use another XSD you write that imports both yours and the xml.xsd and you should be fine. As a not of caution, don't import on the http://www.w3.org/2001/03/xml.xsd schema location, since that link is throttled and you'll get timeouts. Have a local copy and then to that. Something like this:

<?xml version="1.0" encoding="utf-8" ?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:import schemaLocation="..." namespace="http://www.imsglobal.org/xsd/imsrdceo_rootv1p0"/>
    <xsd:import schemaLocation="..." namespace="http://www.w3.org/XML/1998/namespace"/>
</xsd:schema>

QTAssistant diagram for rdceo

Upvotes: 1

Michael Kay
Michael Kay

Reputation: 163262

The element langstring is defined like this:

<xs:anyAttribute namespace="##other" processContents="strict"/>

which means that it allows attributes from another namespace if and only if there is an attribute declaration for that attribute in your schema. Since they don't import the schema for the XML namespace, there's no declaration for xml:lang in the schema unless you take action to include it. I'm not familiar with the PHP interfaces you are using so I can't tell you the best way to achieve that, but one way would be to define a schema document D that imports both the imsglobal schema and the schema for the XML namespace, and use D as the schema against which you validate the instance.

Another way is the way the cited examples do it: they reference the XML namespace from the xsi:schemaLocation attribute in the instance document.

Upvotes: 3

Related Questions