Oracle能在本地文件系统上使用XSD模式验证XML吗?

时间:2021-12-09 17:15:26

I would like to ask a question about XML document validation against its corresponding XML schema(s) and I would appreciate if you could kindly give me a hand. Actually, I've just started learning about XML schemas (I'm totally a beginner). I've purchased the book "Definitive XML Schema" written by Priscilla Walmsley (2nd Edition) which presents XML Schema 1.1 (which I believe is the most recent version).

我想问一个关于针对其对应的XML模式的XML文档验证的问题,如果您能帮助我,我将不胜感激。实际上,我刚刚开始学习XML模式(我完全是个初学者)。我已经购买了Priscilla Walmsley(第二版)所写的《最终XML模式》一书,该书介绍了XML模式1.1(我认为这是最新版本)。

Now the problem is that in all examples and exercices of the book, the namespaces and location of the schema files are given using a web URL.

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

Here is an example of the book:

下面是这本书的一个例子:

This is the schema

这是一个模式

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

And the XML content to be validated against the above mentioned is this

上面提到的要验证的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>

Obviously, [http://datypic.com/prod] is a site maintained by the author, so I cannot add or DELETE any file on this site for my exercices while I'm reading this book. As a result I need to put both XML and XSD documents on my local hard drive (I'm using Linux Fedora Core 17 X86_64). So what I did, was to put the content of the schema in a file named for example 'Example-01.xsd' and the XML content in a file named 'Example-01.xml'.

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

I use oracle PL/SQL package DBMS_XMLSCHEMA (Enterprise Edition 11.2.0.1.0) in order to first register the schema and then call the validate method of XMLType object in order to validate my XML document against the schema, similar to the following link:

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

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

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

I have created a directory (by CREATE DIRECTORY) statement in oracle :

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

/home/train/Documents/myutl_file_dir/

/home/train/Documents/myutl_file_dir /

Where I put both my XML & XSD documents. Here is precisely how I changed the above mentioned XML content in order to refer to XSD locally

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

So if you compare the new XML content with the above mentioned example, the only thing that I added was file:///home/train/Documents/myutl_file_dir/Example-01.xsd at the end of the value of xsi:schemaLocation in order to refer to the local hard drive. I found this method, here:

因此,如果将新的XML内容与上面提到的示例进行比较,我只添加了文件:///home/train/文档/myutl_file_dir/ example -01。在xsi值末尾的xsd:schemaLocation,以便引用本地硬盘驱动器。我在这里找到了这个方法:

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

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

Now, the problem is that it doesn't work. When I run my script in order to validate the document by calling the schemaValidate() method of the XMLType object, here is oracle error message:

现在的问题是它不起作用。当我运行脚本以通过调用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

What I understand from the error message 'Method invalid for non-schema based XML Documents' is that oracle has simply ignored the filepath that I defined for schema file and it considers that there has not been any schema declared for this XML document.

我从错误消息的“方法无效的非模式的XML文档”中理解到,oracle只是忽略了我为架构文件定义的filepath,它认为没有为这个XML文档声明任何模式。

Any idea? How can I deal with this problem?

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

Thanks in advance,

提前谢谢,

Dariyoosh

Dariyoosh

2 个解决方案

#1


7  

OK, after a lot of Googling and thanks to stefan nebesnak' comment I found two problems that caused the error:

好吧,在谷歌上搜索了很久,感谢stefan nebesnak的评论之后,我发现了导致错误的两个问题:

The first one, as Stefan mentioned is that DBMS_XMLSCHEMA.registerSchema can be applied only to schema-based document. Initially what I had done in my PL/SQL code was something like this:

正如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();

So as you can see there is absolutely no link between the registered schema and the XMLType object that refers to my XML document. What I had to do was this:

因此,正如您所看到的,注册的模式和引用我的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')

So, the first problem was solved and my XML document became a schema-based.

因此,第一个问题得到了解决,我的XML文档变成了基于模式的文档。

The second problem was the fact that in the book the XML document to be validated against the schema had been defined in following way:

第二个问题是,在这本书中,根据模式验证的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>

What I understood from 'xsi:schemaLocation="http://datypic.com/prod prod.xsd"' was that the first part of it, that is, http://datypic.com/prod refers to the targetNameSpace and the second part separated by a space, that is, prod.xsd, is used to refer to the location (as an URL) of the schema document which is true. But what I didn't know, was that in oracle DBMS_XMLSCHEMA implementation, this second part must be the very same URL used to register the schema by calling DBMS_XMLSCHEMA.RegisterSchema method, otherwise it will not work. And here is the link to the oracle documentation that confirms this:

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

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

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

If the target XML schema declares a target namespace, then the schemaLocation attribute is used to identify the XML schema. The value of this attribute is a pair of values separated by a space:

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

  • the value of the target namespace declared in the XML schema
  • XML模式中声明的目标名称空间的值
  • the schema location hint, the unique identifier passed to procedure DBMS_XMLSCHEMA.registerSchema when the schema is registered with the database
  • 模式位置提示,传递给过程DBMS_XMLSCHEMA的唯一标识符。在数据库中注册模式时注册模式

And that was precisely what I hadn't done, I had registered the schema with 'http://datypic.com/prod' and just because in the book there was a file name as the second part of the xsi:schemaLocation (prod.xsd) I thought that all I had to do was to put the schema content in a file named for example Example-01.xsd and then provide the file URL to this document, 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.

正是我没有做什么,我已经注册的模式与“http://datypic.com/prod”,因为书中有一个文件名称的第二部分xsi:schemaLocation(prod.xsd)我认为我要做的是把模式内容例如Example-01在文件命名。然后提供该文档的文件URL,文件:///home/train/Documents/myutl_file_dir/Example-01.xsd。这确实是一件愚蠢的事情,因为当您通过调用DBMS_XMLSchema向oracle注册一个模式时。oracle注册XML模式文档的内容。所以oracle需要的是注册过程中使用的schemaURL,它允许查找和标识特定的模式。这正是我的错误,我认为oracle正在寻找我的文件的物理位置。

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)

总结:我已经通过targetNameSpace:“http://datypic.com/prod”注册了这个模式(这只是一个例子,我可以选择其他值)

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

因此,我的XML文档中schemaLocation的正确值是:

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

Dariyoosh

#2


0  

The method can be invoked on only schema based xmltype objects.

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

Try delete and reload documents, before registering an XML schema they reference.

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

Oracle XML DB Developer's Guide:

Oracle XML DB开发人员指南:

When you register an XML schema, keep in mind that the act of registering a schema has no effect on the status of any instance documents already loaded into Oracle XML DB Repository that reference the XML schema. Because the XML schema was not yet registered, such instance documents were non-schema-based when they were loaded. They remain non-schema-based after the schema is registered.

在注册XML模式时,请记住,注册模式的行为不会影响已加载到引用XML模式的Oracle XML DB存储库中的任何实例文档的状态。因为XML模式还没有注册,所以当加载这些实例文档时,它们是非基于模式的。在注册了模式之后,它们仍然是非基于模式的。

You must delete such instance documents, and reload them after registering the schema, in order to obtain schema-based documents.

您必须删除这些实例文档,并在注册模式之后重新加载它们,以便获取基于模式的文档。

Oracle XML Storage Tutorial.

甲骨文XML存储教程。

You can place the schema in the same directory as the XML that references it. In this case, you only need to specify the file name like this:

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

    xsi:noNamespaceSchemaLocation="Example-01.xsd"

(valid relative URI reference)

(有效的相对URI引用)

#1


7  

OK, after a lot of Googling and thanks to stefan nebesnak' comment I found two problems that caused the error:

好吧,在谷歌上搜索了很久,感谢stefan nebesnak的评论之后,我发现了导致错误的两个问题:

The first one, as Stefan mentioned is that DBMS_XMLSCHEMA.registerSchema can be applied only to schema-based document. Initially what I had done in my PL/SQL code was something like this:

正如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();

So as you can see there is absolutely no link between the registered schema and the XMLType object that refers to my XML document. What I had to do was this:

因此,正如您所看到的,注册的模式和引用我的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')

So, the first problem was solved and my XML document became a schema-based.

因此,第一个问题得到了解决,我的XML文档变成了基于模式的文档。

The second problem was the fact that in the book the XML document to be validated against the schema had been defined in following way:

第二个问题是,在这本书中,根据模式验证的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>

What I understood from 'xsi:schemaLocation="http://datypic.com/prod prod.xsd"' was that the first part of it, that is, http://datypic.com/prod refers to the targetNameSpace and the second part separated by a space, that is, prod.xsd, is used to refer to the location (as an URL) of the schema document which is true. But what I didn't know, was that in oracle DBMS_XMLSCHEMA implementation, this second part must be the very same URL used to register the schema by calling DBMS_XMLSCHEMA.RegisterSchema method, otherwise it will not work. And here is the link to the oracle documentation that confirms this:

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

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

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

If the target XML schema declares a target namespace, then the schemaLocation attribute is used to identify the XML schema. The value of this attribute is a pair of values separated by a space:

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

  • the value of the target namespace declared in the XML schema
  • XML模式中声明的目标名称空间的值
  • the schema location hint, the unique identifier passed to procedure DBMS_XMLSCHEMA.registerSchema when the schema is registered with the database
  • 模式位置提示,传递给过程DBMS_XMLSCHEMA的唯一标识符。在数据库中注册模式时注册模式

And that was precisely what I hadn't done, I had registered the schema with 'http://datypic.com/prod' and just because in the book there was a file name as the second part of the xsi:schemaLocation (prod.xsd) I thought that all I had to do was to put the schema content in a file named for example Example-01.xsd and then provide the file URL to this document, 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.

正是我没有做什么,我已经注册的模式与“http://datypic.com/prod”,因为书中有一个文件名称的第二部分xsi:schemaLocation(prod.xsd)我认为我要做的是把模式内容例如Example-01在文件命名。然后提供该文档的文件URL,文件:///home/train/Documents/myutl_file_dir/Example-01.xsd。这确实是一件愚蠢的事情,因为当您通过调用DBMS_XMLSchema向oracle注册一个模式时。oracle注册XML模式文档的内容。所以oracle需要的是注册过程中使用的schemaURL,它允许查找和标识特定的模式。这正是我的错误,我认为oracle正在寻找我的文件的物理位置。

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)

总结:我已经通过targetNameSpace:“http://datypic.com/prod”注册了这个模式(这只是一个例子,我可以选择其他值)

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

因此,我的XML文档中schemaLocation的正确值是:

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

Dariyoosh

#2


0  

The method can be invoked on only schema based xmltype objects.

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

Try delete and reload documents, before registering an XML schema they reference.

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

Oracle XML DB Developer's Guide:

Oracle XML DB开发人员指南:

When you register an XML schema, keep in mind that the act of registering a schema has no effect on the status of any instance documents already loaded into Oracle XML DB Repository that reference the XML schema. Because the XML schema was not yet registered, such instance documents were non-schema-based when they were loaded. They remain non-schema-based after the schema is registered.

在注册XML模式时,请记住,注册模式的行为不会影响已加载到引用XML模式的Oracle XML DB存储库中的任何实例文档的状态。因为XML模式还没有注册,所以当加载这些实例文档时,它们是非基于模式的。在注册了模式之后,它们仍然是非基于模式的。

You must delete such instance documents, and reload them after registering the schema, in order to obtain schema-based documents.

您必须删除这些实例文档,并在注册模式之后重新加载它们,以便获取基于模式的文档。

Oracle XML Storage Tutorial.

甲骨文XML存储教程。

You can place the schema in the same directory as the XML that references it. In this case, you only need to specify the file name like this:

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

    xsi:noNamespaceSchemaLocation="Example-01.xsd"

(valid relative URI reference)

(有效的相对URI引用)