8

我想问一个关于针对相应 XML 模式进行 XML 文档验证的问题,如果您能帮帮我,我将不胜感激。实际上,我刚刚开始学习 XML 模式(我完全是个初学者)。我购买了 Priscilla Walmsley(第 2 版)编写的“Definitive XML Schema”一书,其中介绍了 XML Schema 1.1(我相信它是最新版本)。

现在的问题是,在本书的所有示例和练习中,模式文件的名称空间和位置都是使用 Web URL 给出的。

这是本书的一个例子:

这是架构

<xs:schema  xmlns:xs="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://datypic.com/prod"
            xmlns:prod="http://datypic.com/prod">

    <xs:element name="product" type="prod:ProductType"/>
    <xs:complexType name="ProductType">
        <xs:sequence>
            <xs:element name="number" type="xs:integer"/>
            <xs:element name="size" type="prod:SizeType"/>
        </xs:sequence>
        <xs:attribute name="effDate" type="xs:date"/>
    </xs:complexType>
    <xs:simpleType name="SizeType">
        <xs:restriction base="xs:integer">
            <xs:minInclusive value="2"/>
            <xs:maxInclusive value="18"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

而要针对上述验证的 XML 内容是这样的

<prod:product xmlns:prod="http://datypic.com/prod" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://datypic.com/prod prod.xsd"
          effDate="2011-04-12">
    <number>557</number>
    <size>10</size>
</prod:product>

显然,[http://datypic.com/prod] 是作者维护的站点,因此在阅读本书时,我无法在此站点上添加或删除任何文件以进行练习。因此,我需要将 XML 和 XSD 文档都放在本地硬盘上(我使用的是 Linux Fedora Core 17 X86_64)。所以我所做的就是将架构的内容放在一个名为“Example- 01.xsd ”的文件中,并将 XML 内容放在一个名为“ Example-01.xml ”的文件中。

我使用 oracle PL/SQL 包 DBMS_XMLSCHEMA(企业版 11.2.0.1.0)首先注册架构,然后调用 XMLType 对象的 validate 方法,以便根据架构验证我的 XML 文档,类似于以下链接:

https://forums.oracle.com/forums/thread.jspa?messageID=2462207

我在 oracle 中创建了一个目录(通过 CREATE DIRECTORY)语句:

/home/train/Documents/myutl_file_dir/

我把我的 XML 和 XSD 文档放在哪里。这正是我更改上述 XML 内容以便在本地引用 XSD 的方式

<prod:product xmlns:prod="http://datypic.com/prod" 
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://datypic.com/prod file:///home/train/Documents/myutl_file_dir/Example-01.xsd"
               effDate="2011-04-12">
    <number>557</number>
    <size>10</size>
</prod:product>

因此,如果您将新的 XML 内容与上述示例进行比较,我添加的唯一内容是file:///home/train/Documents/myutl_file_dir/Example-01.xsd在xsi:schemaLocation的值末尾命令指的是本地硬盘。我在这里找到了这个方法:

http://lists.w3.org/Archives/Public/xmlschema-dev/2001Dec/0161.html

现在,问题是它不起作用。当我运行脚本以通过调用 XMLType 对象的 schemaValidate() 方法来验证文档时,这里是 oracle 错误消息:

BEGIN
*
ERROR at line 1:
ORA-19030: Method invalid for non-schema based XML Documents.
ORA-06512: at "SYS.XMLTYPE", line 354
ORA-06512: at "TRAIN2012.ZXML_PKG", line 176
ORA-06512: at line 2

我从错误消息“ Method invalid for non-schema based XML Documents”中了解到,oracle 只是忽略了我为模式文件定义的文件路径,它认为没有为此 XML 文档声明任何模式。

任何的想法?我该如何处理这个问题?

提前致谢,

达里约什

4

2 回答 2

8

好的,经过大量谷歌搜索并感谢 stefan nebesnak 的评论,我发现了两个导致错误的问题:

第一个,正如 Stefan 所提到的,DBMS_XMLSCHEMA.registerSchema 只能应用于基于模式的文档。最初,我在 PL/SQL 代码中所做的事情是这样的:

l_xml_file_content := XMLType('Here I put the content of my XML document')
l_xml_file_content.schemaValidate();

如您所见,注册模式和引用我的 XML 文档的 XMLType 对象之间绝对没有链接。我必须做的是:

l_xml_file_content := 
   XMLType(
            'Here I put the content of my XML document'
          ).createSchemaBasedXML('and here I put the very same schema URL used during registereation while I registered the schema by calling the DBMS_XMLSCHEMA.registerSchema method')

所以,第一个问题解决了,我的 XML 文档变成了基于模式的。

第二个问题是,在本书中,要针对模式进行验证的 XML 文档是按以下方式定义的:

<prod:product xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns:prod="http://datypic.com/prod"
              xsi:schemaLocation="http://datypic.com/prod prod.xsd" 
              effDate="2011-04-12">

    <number>557</number>
    <size>10</size>
</prod:product>

我从 ' xsi:schemaLocation="http://datypic.com/prod prod.xsd" ' 中了解到的是它的第一部分,即http://datypic.com/prod指的是 targetNameSpace 和第二部分由空格分隔,即prod.xsd,用于引用模式文档的位置(作为 URL),这是真的。但我不知道的是,在 oracle DBMS_XMLSCHEMA 实现中,这第二部分必须是用于通过调用 DBMS_XMLSCHEMA.RegisterSchema 方法注册模式的相同 URL,否则它将不起作用。这是确认这一点的 oracle 文档的链接:

http://docs.oracle.com/cd/B19306_01/appdev.102/b14259/xdb03usg.htm#BABBGBDA

如果目标 XML 模式声明了目标名称空间,则 schemaLocation 属性用于标识 XML 模式。该属性的值是一对用空格分隔的值:

  • XML 模式中声明的目标命名空间的值
  • 模式位置提示,当模式注册到数据库时传递给过程 DBMS_XMLSCHEMA.registerSchema 的唯一标识符

这正是我没有做的,我已经用' http://datypic.com/prod '注册了模式,只是因为在书中有一个文件名作为 xsi:schemaLocation 的第二部分(产品.xsd) 我认为我所要做的就是将架构内容放在一个名为 Example-01.xsd 的文件中,然后提供该文档的文件 URL,file:///home/train/Documents/myutl_file_dir /Example-01.xsd. Which was really a silly thing because, when you register a schema with oracle by calling the DBMS_XMLSchema.registerSchema, oracle registers the content of the XML schema document. So what oracle needs is the schemaURL used during registeration which allows to find and identify uniquely the specific schema. And this was exactly my mistake I had thought that oracle is looking for physical location of my file.

Conclusion: I had registered the schema by the targetNameSpace : 'http://datypic.com/prod' (well, it was just an example, I could have chosen other value)

So, the correct value of schemaLocation inside my XML document was this:

xsi:schemaLocation="http://datypic.com/prod prod.xsd 
                    http://datypic.com/prod prod.xsd"

And this solved the problem.

I hope this can help those who have encountered the same problem.

Regards,

Dariyoosh

于 2012-11-08T17:12:22.247 回答
0

该方法只能在基于模式的xmltype 对象上调用。

在注册他们引用的 XML 模式之前,尝试删除并重新加载文档。

Oracle XML DB 开发人员指南

注册 XML 模式时,请记住,注册模式的行为不会影响已加载到引用 XML 模式的 Oracle XML DB 存储库中的任何实例文档的状态。由于 XML 模式尚未注册,因此此类实例文档在加载时不是基于模式的。在模式注册后,它们仍然是非基于模式的。

您必须删除此类实例文档,并在注册模式后重新加载它们,以获得基于模式的文档。

Oracle XML 存储教程

您可以将架构放置在与引用它的 XML 相同的目录中。在这种情况下,您只需要像这样指定文件名:

    xsi:noNamespaceSchemaLocation="Example-01.xsd"

(有效的相对 URI 引用)

于 2012-11-06T18:24:47.943 回答