文档末尾的额外内容,引用我的根元素作为问题

时间:2016-02-26 02:49:23

标签: xml xsd xml-parsing schema xsd-validation

我是XML的新手,最近我获得了两项涉及XML和Schema的任务。如果我取出模式,浏览器会显示XML,但是当我添加模式时,我会在根元素上收到错误,指出文档末尾有额外的内容。我在这里查看了一些答案,其中大多数都有两个根元素,或者一个元素名称中的空格,但这不是问题。

我知道这很简单,但我一直在寻找几个小时,并且确实碰到了这个问题。

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3schools.com"
xmlns="http://www.w3schools.com"
elementFormDefault="qualified">
<xsd:element name="table">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element name="id" type="xsd:string"/>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="stars">
                <xsd:simpletype>
                    <xsd:restriction base="xsd:positiveinteger">
                        <xsd:mininclusive value="0"/>
                        <xsd:maxinclusive value="5"/> 
                    </xsd:restriction>
                </xsd:simpletype>
            </xsd:element>
            <xsd:element name="facilities">
                <xsd:simpletype>
                    <xsd:restriction base="xsd:string">
                        <xsd:enumeration value="Internet"/>
                        <xsd:enumeration value="Gym"/>
                        <xsd:enumeration value="Parking"/>
                        <xsd:enumeration value="Restaurant"/>
                        <xsd:enumeration value="Pick-up"/>
                    </xsd:restriction>
                </xsd:simpletype>
            </xsd:element>
            <xsd:element name="address" type="xsd:string"/>
            <xsd:element name="distancefromcenter" type="xsd:integer" minoccurs="0"/>
            <xsd:element name="available" type="xsd:boolean"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>
</xsd:schema>
<table>
    <hotel>
        <id>1</id>
        <name>Les Jardins du Marais</name>
        <stars>3</stars>
        <facilities>Internet</facilities>
        <address>74 rue Amelot, Paris, 75011</address>
        <distancefromcenter>2</distancefromcenter>
        <available>True</available>
    </hotel>

    <hotel> 
        <id>2</id>
        <name>Golden Tulip Little Palace</name>
        <stars>4</stars>
        <facilities>Internet Gym Parking Restaurant</facilities>
        <address>4 rue Salomon De Caus, Paris, 75003</address>
        <distancefromcenter>0.1</distancefromcenter>
        <available>False</available>
    </hotel>

    <hotel> 
        <id>3</id>
        <name>Tilsitt Etoile</name>
        <stars>2</stars>
        <facilities>Restaurant</facilities>
        <address>23 rue Brey, Paris, 75017</address>
        <distancefromcenter>3</distancefromcenter>
        <available>False</available>
    </hotel>

    <hotel> 
        <id>4</id>
        <name>Hotel Saint Charles</name>
        <stars> 3</stars>
        <facilities>Parking</facilities>
        <address>6 rue de I'Esperance, Paris, 75013</address>
        <distancefromcenter>1</distancefromcenter>
        <available>True</available>
    </hotel>
</table>

2 个答案:

答案 0 :(得分:1)

XSD不能与XML文档 1 位于同一文件中。如果您按照示例中所示将两者一起呈现,则您有两个根元素,并且在XML中从不允许这样做。

而是使用schemaLocation或noNamespaceSchemaLocation来向XML处理器提示有关XSD位置的信息(在单独的文件中)。

请参阅How to link XML to XSD using schemaLocation or noNamespaceSchemaLocation?

1 对于希望根据XSD验证XML的实践者而言,没有任何非实际价值的非自然扭曲。但请参阅C. M. Sperberg-McQueen's interesting assessment理论上的XSD,就像之前的DTD一样,可能存在于它要管理的同一XML文档中。

答案 1 :(得分:1)

实际上,您通常希望将XML实例文档及其架构放在不同的XML文档中;使用验证程序提供的命令行选项或调用参数指向架构。如果您的验证器没有提供合适的命令行选项,并且您无法将其破解并获得具有更好设计界面的验证器,那么您可能可以使用提到的xsi:schemaLocationxsi:noNamespaceSchemaLocation属性通过kjhughes。

但是说XSD'模式文档'(XSD规范定义为'xsd:schema元素')和要验证的XML 不能在相同的XML文档。原则上很可能。

但是如果你想这样做,你需要做一些改变。

首先,制作格式良好的XML文档。一种简单的方法是在包装器中包装现有材料(一个xsd:schema元素和一个table元素):

<wrapper>
  <xsd:schema targetNamespace="http://example.com/ns/BryanM."
              xmlns="http://example.com/ns/BryanM."
              elementFormDefault="qualified"
              id="myschema">
    ...
  </xsd:schema>
  <table xmlns="http://example.com/ns/BryanM.">
    ...
  </table>
</wrapper>

另一种方法是在表格中嵌入xsd:schema元素。

<table xmlns="http://example.com/ns/BryanM.">
  <xsd:schema targetNamespace="http://example.com/ns/BryanM."
              xmlns="http://example.com/ns/BryanM."
              elementFormDefault="qualified"
              id="myschema">
    ...
  </xsd:schema>
  <hotel>
    ...
  </hotel>
  ...
</table>

我在架构元素上提供了xml:id属性,原因很快就会变得清晰。

我还将目标命名空间从w3schools.com(您不应该将其用于您的架构,除非您是该域的所有者)更改为主机名为example.com的命名空间(保留用于例子);这与模式有效性无关,只与正确使用名称空间有关。

其次,您需要告诉验证器在哪里找到您的架构。您正在使用的验证器可以为该信息提供命令行选项或调用参数,在这种情况下,您可以使用它们指向xsd:schema元素;否则,您可能希望将以下内容添加到包装器或表元素中:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/ns/BryanM. #myschema"

正如您可能看到的,这个xsi:schemaLocation属性实际上说“嗨,那里,XSD验证器!如果您还没有名称空间http://example.com/ns/BryanM.的模式,您可以在URI #myschema,即此文档中ID为myschema的元素。“这就是xsd:schema元素需要携带ID的原因。

第三,您需要告诉验证者您要针对架构验证哪个元素,或者(可能更有可能)确保它可以验证文档的根元素(第一个示例中的包装器,表中的第二)。很少有带命令行界面的XSD验证器实际上提供了一个选项,用于识别您希望它们验证哪些XML元素;他们只是默默地假设他们被要求验证整个文档。通过API调用的Validator函数我认为更有可能提供该功能。

如果您的验证器坚持验证整个XML文档(有些人会这样做),那么您需要确保您的架构能够胜任工作;最简单的方法,如果你使用'wrapper'元素,就是添加像

这样的东西
<xsd:element name="wrapper"/>

到架构。 (根据验证器如何处理XSD 1.0中某些实现定义的行为,这可能是也可能不是绝对必要的。)如果您正在使用第二种方法(在表元素中嵌入模式),则需要修改'table'元素允许它包含一个名为'xsd:schema'的子元素;我不会在这里详述。

不幸的是,尽管原则这一切都是可能的,但事实是验证器之间的互操作性很小,它允许将模式嵌入到输入XML文档中;该规范没有给出任何指导,并且XSD工作组应该编写一份描述推荐做法的说明的提议由于工作组对这种说明的效用缺乏共识而失败(或甚至对现有做法进行调查的效用) 。因此,虽然我认为,正如kjhughes所做的那样,架构不能与要验证的输入在同一XML文档中是不正确的,但在实践中它几乎总是更好