1

I am quite new to XML validation so sorry for the elementary question. I have the following document:

<tincan xmlns="http://projecttincan.com/tincan.xsd">
  <activities>
    <activity id="TestActivity" type="course">
      <name lang="und">MyCourse</name>
      <description lang="und"/>
      <launch lang="und">start.html</launch>
    </activity>
    <activity id="p001" type="objective">
      <name lang="und">First Page</name>
      <description lang="und">First Page</description>
    </activity>
  </activities>
</tincan>

I am trying to validate it against the following schema: http://projecttincan.com/tincan.xsd (I also tried removing the schema from my XML and providing it externally).

I always get the following exception: cvc-elt.1: Cannot find the declaration of element 'tincan'

By looking into the schema, I see that the tincan element is defined there and it is also present in my XML so I don't udnerstand what is the source of this exception. I would be glad if someone could explain how the validation is supposed to work.

EDIT: My code for the validation:

DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = parser.parse(stream);

// create a SchemaFactory capable of understanding WXS schemas
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

// load a WXS schema, represented by a Schema instance
Source schemaFile = new StreamSource(getClass().getClassLoader().getResource("tincan.xsd").getFile());
Schema schema = factory.newSchema(schemaFile);

// create a Validator instance, which can be used to validate an instance document
Validator validator = schema.newValidator();

// validate the DOM tree
validator.validate(new DOMSource(document));

EDIT2: Schema was linked here but I will post it here again for clarity:

<xs:schema xmlns="http://projecttincan.com/tincan.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tc="http://projecttincan.com/tincan.xsd" targetNamespace="http://projecttincan.com/tincan.xsd" elementFormDefault="qualified">
<xs:element name="tincan" type="tincan"></xs:element>
<xs:complexType name="tincan">
<xs:sequence>
<xs:element name="activities" type="activities" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="activity">
<xs:sequence>
<xs:element name="name" type="langstring" maxOccurs="unbounded"/>
<xs:element name="description" type="langstring" maxOccurs="unbounded"/>
<xs:element name="launch" type="langURI" maxOccurs="unbounded" minOccurs="0"/>
<xs:element name="resource" type="langURI" maxOccurs="unbounded" minOccurs="0"/>
<xs:element name="interactionType" type="xs:string" minOccurs="0"/>
<!--  CMI Interaction fields  -->
<xs:element name="correctResponsePatterns" type="correctResponsePatternList" minOccurs="0"/>
<xs:element name="choices" type="interactionComponentList" minOccurs="0"/>
<xs:element name="scale" type="interactionComponentList" minOccurs="0"/>
<xs:element name="source" type="interactionComponentList" minOccurs="0"/>
<xs:element name="target" type="interactionComponentList" minOccurs="0"/>
<xs:element name="steps" type="interactionComponentList" minOccurs="0"/>
<!--  Extensions -->
<xs:element name="extensions" type="extensions" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="id" type="xs:anyURI"/>
<xs:attribute name="type" type="xs:string"/>
</xs:complexType>
<xs:complexType name="activities">
<xs:sequence>
<xs:sequence>
<xs:element name="activity" type="activity" maxOccurs="unbounded"/>
<xs:element name="provider" type="provider" minOccurs="0"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
<xs:complexType name="provider">
<xs:all>
<xs:element name="name" type="langstring"/>
<xs:element name="id" type="xs:string"/>
<xs:element name="secret" type="xs:string" minOccurs="0"/>
<xs:element name="public_key" type="xs:string" minOccurs="0"/>
<xs:element name="info" type="xs:anyURI" minOccurs="0"/>
</xs:all>
</xs:complexType>
<xs:complexType name="correctResponsePatternList">
<xs:sequence>
<xs:element name="correctResponsePattern" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="interactionComponentList">
<xs:sequence>
<xs:element name="component" type="interactionComponentType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="interactionComponentType">
<xs:sequence>
<xs:element name="id" type="xs:string"/>
<xs:element name="description" type="langstring" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="langstring">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="lang" type="xs:language"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="extensions">
<xs:sequence>
<xs:element name="extension" type="extension" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="extension">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="key" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="langURI">
<xs:simpleContent>
<xs:extension base="xs:anyURI">
<xs:attribute name="lang" type="xs:language"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>

2 Answers 2

6

Make your document builder "namespaceAware" should fix it!

  DocumentBuilderFactory f=DocumentBuilderFactory.newInstance();          
  f.setNamespaceAware(true);

You can also operate directly on a Source object, which makes code a little bit shorter, it's also likely to be faster and use less memory.

Sample with both variants

package stack43324079;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.junit.Test;
import org.w3c.dom.Document;

public class HowToValidateXml {
    @Test
    public void validate1() throws Exception {
        DocumentBuilderFactory f=DocumentBuilderFactory.newInstance();
        f.setNamespaceAware(true);
        DocumentBuilder parser = f.newDocumentBuilder();
        Document document = parser.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("43324079.xml"));
        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Source schemaFile = new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream("tincan.xsd"));
        Schema schema = factory.newSchema(schemaFile);
        Validator validator = schema.newValidator();
        validator.validate(new DOMSource(document));
    }

    @Test
    public void validate2() throws Exception {
        Source xmlFile = new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream("43324079.xml"));
        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = factory.newSchema(Thread.currentThread().getContextClassLoader().getResource("tincan.xsd"));
        Validator validator = schema.newValidator();
        validator.validate(xmlFile);
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. Works like a charm.
Note also, using a StreamSource not only makes the code shorter, it's also likely to be faster and use less memory.
0

You're not showing us the schema, so we can only guess what's wrong, but my guess would be that the element is declared in the wrong namespace.

If that's a wrong guess, then try to remember next time you ask a question that it's very hard to find bugs in code when people don't show you the code.

5 Comments

The schema is referenced in my question. I just did not include the code because it's long. You can find it here: tincanapi.com/wp-content/assets/tincan.xsd
The schema is referenced in the xml file <tincan xmlns="http://projecttincan.com/tincan.xsd">
Questions should be self-contained, so (a) they still make sense when someone with a similar question comes here in several years time, and (b) so that those of us who are wary of following links supplied by strangers don't have to take the risk.
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - From Review
@sidgate It was a reasonable guess at an answer given the very limited information provided in the post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.