So there's an XSD schema that validates a data file.
It declares root element of the document, and then go complexType
's that describe structure. The schema has empty target namespace, document nodes are not supposed to be qualified with a namespace.
Recently someone by mistake sent an XSL template in place of an XML data file. That xsl passed validation no problem and was therefore directed to the XSLT processor. Result was basically the free-form text found in the validated XSL.
We then sent all sorts of XML documents to the validator (like, various XSD schemas and XSL templates), and they all passed validation.
We tried different ways of validation (XPathDocument.CheckValidity and XMLDocument.Validate), no difference.
What is happening anyway? Is our validation schema happy to pass any documents whose root nodes are qualified to a namespace different to what the schema describes? How do we prevent that?
EDIT
Validation code (version 1):
Dim data As XPathDocument
....
If Not data.CreateNavigator.CheckValidity(ValidationSchemaSet, AddressOf vh.ValidationHandler) Then
result = "Validation failed." & ControlChars.NewLine & String.Join(ControlChars.NewLine, vh.Messages.ToArray)
Return False
End If
, where vh is:
Private Class VHandler
Public Messages As New List(Of String)
Public Sub ValidationHandler(ByVal sender As Object, ByVal e As ValidationEventArgs)
If e.Severity = XmlSeverityType.Error Then
Messages.Add(e.Message)
End If
End Sub
End Class
XSD schema:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="CarrierLabel_Type_1.xsd" />
<xs:include schemaLocation="CarrierLabel_Type_2.xsd" />
<xs:include schemaLocation="CarrierLabel_Type_3.xsd" />
<!-- Schema definition -->
<xs:element name="PrintJob" type="printJobType" />
<!-- Types declaration -->
<xs:simpleType name="nonEmptyString">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="printJobType">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:choice>
<xs:element name="CarrierLabel_type_1" type="CarrierLabel_type_1" />
<xs:element name="CarrierLabel_type_2" type="CarrierLabel_type_2" />
<xs:element name="CarrierLabel_type_3" type="CarrierLabel_type_3" />
</xs:choice>
</xs:sequence>
<xs:attribute name="printer" type="nonEmptyString" use="required" />
<xs:attribute name="res" type="xs:positiveInteger" use="required" />
</xs:complexType>
</xs:schema>
Should (and will) pass:
<?xml version='1.0' encoding='utf-8'?>
<PrintJob printer="printer_1" res="200">
<CarrierLabel_type_1>
<print_job_id>123456</print_job_id>
<notes></notes>
<labels_count>1</labels_count>
<cases_indicator>2xCASE</cases_indicator>
</CarrierLabel_type_1>
<CarrierLabel_type_2>
<next_location>Go there now!</next_location>
</CarrierLabel_type_2>
</PrintJob>
Should not pass, but WILL PASS AS VALID DATA:
<?xml version='1.0' encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="WrongLabel">
<xsl:param name="context"/>
<xsl:param name="res"/>
WRONG LABEL
</xsl:template>
</xsl:stylesheet>