2014-04-01 51 views
6

對嵌套元素進行不一致的XSD驗證我正在研究一種工具來幫助用戶編寫與JSP文件性質相似的XHTML-ish文檔。這些文檔是XML文檔,可以在XHTML命名空間中包含任何格式正確的標籤,並且它們之間編織的是我產品命名空間中的元素。除此之外,該工具使用XSD驗證輸入。使用'<xs:any>'

例輸入:

<?xml version="1.0"?> 
<markup> 
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="https://my_tag_lib.example.com/"> 
    <c:section> 
     <c:paragraph> 
     <span>This is a test!</span> 
     <a href="http://www.google.com/">click here for more!</a> 
     </c:paragraph> 
    </c:section> 
    </html> 
</markup> 

我的問題是,XSD驗證不行爲一致取決於我窩有多深的元素。我想要的是https://my_tag_lib.example.com/命名空間中的所有元素都要根據模式進行檢查,而命名空間http://www.w3.org/1999/xhtml中的任何元素都可以被寬鬆地容忍。我不想列出在我的XSD中允許使用的所有HTML元素 - 用戶可能想要使用僅在某些瀏覽器上可用的模糊元素等。相反,我只想列出使用<xs:any>屬於名稱空間的任何元素。

我發現的是,在某些情況下,屬於my_tag_lib名稱空間但未出現在模式中的元素是通過驗證,而出現在模式中的其他元素可以通過給出他們無效的屬性。

因此: *針對XSD模式驗證有效元素 *驗證程序跳過了無效元素?

例如,這個通過驗證:

<?xml version="1.0"?> 
<markup> 
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="https://my_tag_lib.example.com/"> 
    <c:section> 
     <div> 
     <c:my-invalid-element>This is a test</c:my-invalid-element> 
     </div> 
    </c:section> 
    </html> 
</markup> 

但後來這個驗證失敗:

<?xml version="1.0"?> 
<markup> 
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="https://my_tag_lib.example.com/"> 
    <c:section> 
     <div> 
     <c:paragraph my-invalid-attr="true">This is a test</c:paragraph> 
     </div> 
    </c:section> 
    </html> 
</markup> 

爲什麼屬性進行驗證的架構爲公認的元素,而未知的元素看似不得到消毒了嗎?這裏的邏輯是什麼?我一直在使用xmllint做驗證:

xmllint --schema markup.xsd example.xml 

這裏是我的XSD文件:

文件:markup.xsd

<?xml version="1.0" encoding="ISO-8859-1" ?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xhtml="http://www.w3.org/1999/xhtml"> 
    <xs:import namespace="http://www.w3.org/1999/xhtml" schemaLocation="html.xsd" /> 
    <xs:element name="markup"> 
    <xs:complexType mixed="true"> 
     <xs:sequence> 
     <xs:element ref="xhtml:html" /> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

文件:html.xsd

<?xml version="1.0" encoding="ISO-8859-1" ?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3.org/1999/xhtml"> 
    <xs:import namespace="https://my_tag_lib.example.com/" schemaLocation="my_tag_lib.xsd" /> 
    <xs:element name="html"> 
    <xs:complexType mixed="true"> 
     <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:any processContents="lax" namespace="http://www.w3.org/1999/xhtml" /> 
     <xs:any processContents="strict" namespace="https://my_tag_lib.example.com/" /> 
     </xs:choice> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

文件: my_tag_lib.xsd

<?xml version="1.0" encoding="ISO-8859-1" ?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="https://my_tag_lib.example.com/"> 
    <xs:element name="section"> 
    <xs:complexType mixed="true"> 
     <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:any processContents="lax" namespace="http://www.w3.org/1999/xhtml" /> 
     <xs:any processContents="strict" namespace="https://my_tag_lib.example.com/" /> 
     </xs:choice> 
    </xs:complexType> 
    </xs:element> 
    <xs:element name="paragraph"> 
    <xs:complexType mixed="true"> 
     <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:any processContents="lax" namespace="http://www.w3.org/1999/xhtml" /> 
     <xs:any processContents="strict" namespace="https://my_tag_lib.example.com/" /> 
     </xs:choice> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

回答

1

div元素不聲明的,所以沒有什麼保留,如果從不接受您的模式無效類型和paragraph元素不允許my-invalid-attr

也許一些例子可能會更清楚。

如果元素被聲明(如htmlsectionparagraph)及其內容是從標籤庫名稱空間(你聲明爲具有processContents="strict")時,它們將被視爲嚴格。這意味着必須聲明屬性或子元素。這應該驗證失敗:

<html> 
    <c:my-invalid-element>This is a test</c:my-invalid-element> 
</html> 

所以將這樣的:

<c:section> 
    <c:my-invalid-element>This is a test</c:my-invalid-element> 
</c:section> 

這樣的:

<div> 
    <c:paragraph> 
     <c:my-invalid-element>This is a test<c:my-invalid-element> 
    </c:paragraph> 
</div> 

這(因爲屬性的內容部分):

<c:paragraph my-invalid-attr="true">This is a test</c:paragraph> 

但是如果元素是不是宣佈(如div),它將匹配xs:any聲明。沒有聲明限制div的內容,所以它允許任何內容。因此,這應該驗證:

<div> 
    <c:my-invalid-element>This is a test</c:my-invalid-element> 
</div> 

而且,由於c:my-invalid-element還沒有宣佈,它將允許任何內容或屬性。這是有效的:

<div> 
    <c:my-invalid-element invalid-attribute="hi"> <!-- VALID --> 
     <c:invalid></c:invalid> 
     <html></html> 
    </c:my-invalid-element> 
</div> 

但是,如果你把裏面一個html無效元素,它將失敗:

<div> 
    <c:my-invalid-element invalid-attribute="hi"> 
     <html><c:invalid></c:invalid></html> <!-- NOT VALID --> 
    </c:my-invalid-element> 
</div> 

如果使用未聲明的屬性聲明的元素中同樣會發生(這將不匹配xs:any)不管你的嵌套有多深:

<div> 
    <c:my-invalid-element invalid-attribute="hi"> <!-- VALID --> 
     <c:invalid> 
      <b> 
       <c:section bad-attribute="boo"></c:section> <!-- FAILS! --> 
... 
2

你錯過了什麼是context determined declaration的理解。

首先,看看這個小實驗。

<?xml version="1.0"?> 
<markup> 
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="https://my_tag_lib.example.com/"> 
     <c:section> 
      <div> 
       <html> 
        <c:my-invalid-element>This is a test</c:my-invalid-element> 
       </html> 
      </div> 
     </c:section> 
    </html> 
</markup> 

這是與您的有效例子,但現在我已經改變了c中的背景:我-無效元素正在從「寬鬆」到「嚴格」評估。這是通過插入html元素完成的,該元素現在強制標記名稱空間中的所有元素都是嚴格的。正如您可以輕鬆確認的,上述內容無效。

這告訴你(沒有閱讀documentation)在你的例子中,確定的上下文肯定是「鬆懈」,而不是你的期望,這是「嚴格的」。

爲什麼上下文不嚴格? div是「懶散」處理的(它與通配符匹配,但沒有定義),因此它的孩子會被懶散地評估。匹配鬆弛的含義:在第一種情況下,找不到c:my-invalid-element的定義,因此給出的指令是don't worry if you can't - 都很好。在無效樣本中,可以找到c:paragraph的定義,因此it must be ·valid· with respect to that definition - 由於意外的屬性而不太好。

+0

因此,無法強制一個名稱空間中的所有元素都是嚴格的 - 它都基於當前上下文嗎? –

+0

@RichardJPLeGuen,那是對的。 –