代码之家  ›  专栏  ›  技术社区  ›  GSerg

XSD:XML文件通过了验证,但xsl和XSD也通过了验证

  •  0
  • GSerg  · 技术社区  · 16 年前

    所以有一个XSD模式来验证数据文件。 它声明文档的根元素,然后转到 complexType

    最近有人错误地发送了一个XSL模板来代替XML数据文件。xsl通过验证没有问题,因此被定向到XSLT处理器。结果基本上是在经过验证的XSL中找到的自由格式文本。

    我们尝试了不同的验证方法(XPathDocument.CheckValidity和XMLDocument.Validate),没有区别。

    到底发生了什么?我们的验证模式是否乐于将其根节点限定为与模式描述不同的名称空间的任何文档传递出去?我们如何防止这种情况?

    编辑

    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
    

    ,其中vh为:

    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
    

    <?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>
    

    如果(并将)通过:

    <?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>
    

    不应通过,但将作为有效数据通过:

    <?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>
    
    4 回复  |  直到 16 年前
        1
  •  1
  •   Robert Rossney    16 年前

    XML模式真正验证命名空间中的元素,而不是文档。没有XML模式规则规定实例文档的顶级元素必须位于特定名称空间内。这符合名称空间是它自己的小世界这一一般想法,它阻止我在名称空间中编写一个将使您的文档无效的模式。如果某个元素不在我的命名空间中,那与我无关

    这意味着在验证实例文档时,必须检查以确保要验证的文档的顶级元素位于应用程序接受的名称空间中—在应用程序中,该名称空间只是默认名称空间。

        2
  •  0
  •   Wim    16 年前

    在没有看到任何代码的情况下,我想尝试一下,并建议 也许 可能是因为您的验证正在设置 ValidationType 上 XmlReaderSettings 对象,但您要么没有连接 ValidationEventHandler 检查验证错误或只是不处理这些验证事件。

    MSDN here .

        3
  •  0
  •   Vincent Marchetti    16 年前

    我的理解是,XMLSchema(XSD)没有提供任何方式来要求文档的根节点是某个元素——唯一的方法是将在“全局级别”定义的元素限制为一个元素。验证代码是否可能正在导入XSLT的模式,以便在看到XSLT文档时进行验证,因为XSLT元素是在全局级别定义的。

        4
  •  0
  •   GSerg    16 年前

    正确的。

    事实证明,验证有三种可能的结果,而不是两种——有效、无效和未知。所以布尔返回值 CheckValidity 功能有点令人惊讶。

    如果架构未描述文档的根节点,则文档通过验证时不会出错,也不会发生任何验证事件,但根节点接收到“未知”状态。就我们而言,这是一次失败。因此,我们还需要检查根节点的XMLNode.SchemaInfo.Validity成员。

    我希望 Validate() 方法文档在这方面更清楚一些。