zhulien
zhulien

Reputation: 557

XML Namespaces, Schema validation(XSD) and XSLT

I have a XML file with the following structure:

<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="studentsStylesheet.xsl"?>
<students xmlns="urn:students">
  <student>
    ...
  </student>
</students>

A XSD schema:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="urn:students"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="students">
    ...        
  </xs:element>
</xs:schema>

And a XSL file for visualization(studentsStylesheet.xsl):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html>
      ...
    </html>
  </xsl:template>
</xsl:stylesheet>

I am currently taking a short course on XML and have a task to construct a given XSD schema and some sample records in a XML file and then visualize the content as a HTML in the end using XSLT. One of the tasks stated that I need to use "urn:students" as a default namespace for the structure. However, when I do that, I don't receive the data in the final visualization. When I remove the "xmlns="urn:students"" from the XML file, everything works fine. I have read a couple of materials and tutorials on XML namespaces, but I just got more confused. It should be the same as in the normal programming languages, but in the same time it is quite different. I didn't find a clear explanation about the following things:

  1. How to link a XML to a schema? Do I need to link the file to the schema or vice versa? On every article/tutorial I read, there was a different way to achieve that and it was not explained why.
  2. Which namespaces should I include in such a situation in both the XML and the Schema.

I also can't understand what's the exact problem with the "xmlns="urn:students"" definition in the XML file. Aren't the elements defined properly in the schema, which has the same namespace? Why can't the XSL pull the data?

Upvotes: 2

Views: 2995

Answers (2)

C. M. Sperberg-McQueen
C. M. Sperberg-McQueen

Reputation: 25034

To answer your question 1:

How to link a XML to a schema? Do I need to link the file to the schema or vice versa? On every article/tutorial I read, there was a different way to achieve that and it was not explained why.

There is no requirement to point from a document to its XSD schema, but there are environments and situations in which it's convenient to do so. Most schemas are intended to handle an indefinitely large number of documents, so in the usual case it would be very cumbersome to point from the schema to the document; for that reason, perhaps, there are not standard ways of pointing from schema document to instance document.

Your options include these:

Naming the schema at validation time

If you want to validate an XML document against a particular schema, the most reliable way is to specify both the URI of the XML document and the URI of the schema documents you want, in the invocation of the validator. Most XSD validators should have an invocation interface that allows you to do this. (If the validator you're using doesn't, my recommendation is to get a new validator. But you should make your own decision on that.)

This approach does not require anything in the XML document to point to the schema documents; it is the only reliable way to validate documents received from an untrusted source (since if you don't trust them to provide a valid document, you probably also don't trust them to point to the correct or agreed-upon schema documents).

Using xsi:schemaLocation

If you want to point to a schema from the XML document, as a way of documenting the meaning of the document or to save yourself typing when invoking a validator, the XSD spec defines a way: use an xsi:schemaLocation attribute in your XML document. The attribute value contains a sequence of space-delimited URI pairs: namespace name, then URI for the schema document for that namespace. So your XML document might start like this:

<students 
  xmlns="urn:students"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsl:schemaLocation="urn:students
    http://yoursite.example.com/2015/students.xsd"
> ...

Many XSD validators will default to reading the schema documents named in xsi:schemaLocation attributes, if you don't specify any schema documents when you invoke the validator.

Using the xml-model processing instruction

W3C has defined a generic schema-linkage mechanism analogous to the xml-stylesheet processing instruction; you can use it in lieu of, or in addition to, the xsi:schemaLocation attribute, if you wish. The beginning of your XML might then look like:

<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" 
  href="studentsStylesheet.xsl"?>
<?xml-model type="application/xml"
  schematypens="http://www.w3.org/2001/XMLSchema"
  href="http://www.w3.org/2001/XMLSchema" 
  title="My excellent XSD Schema"?>
<students xmlns="urn:students"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsl:schemaLocation="urn:students
    http://yoursite.example.com/2015/students.xsd"
>

The type pseudo-attribute can often be omitted (the validator will find out the MIME type of the schema when it dereferences the URI), and the schematypens may also be omissible (the validator will see, when it gets the schema, what kind of schema it is); the title pseudo-attribute is there for use by software that can use it.

There may be XSD validators which will can read and understand xml-model processing instructions and consult the specified schema document(s) if no schema documents are specified in the invocation of the validator; I don't know of any off-hand, but I haven't looked at this issue lately. If the purpose of the link is to document the conceptual framework of the XML instance, of course, that doesn't matter: human readers can use the processing instruction to find the schema you intend to be valid against.

Upvotes: 2

JLRishe
JLRishe

Reputation: 101662

It sounds like your XML and XSD are (probably) ok and that the problem lies in your XSLT.

XPath 1.0 doesn't allow for a default namespace. Any XPath segments without a prefix are treated as referring to the "null namespace".

In order to refer to a namespace in your XPaths, you need to assign it a prefix (in the XSLT):

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:st="urn:students">

and then use it in your XPaths:

<xsl:value-of="st:Students/st:Student" />

Upvotes: 2

Related Questions