Oracle 能否使用本地文件系统上的 XSD 模式验证 XML?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13223246/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can Oracle validate XML using an XSD schema on the local file system?
提问by dariyoosh
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 编写的“Definitive XML Schema”一书(第 2 版),其中介绍了 XML Schema 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)。所以我所做的,就是把模式的内容在一个名为例如“文件示例- 01.xsd”和一个名为“文件的XML内容示例- 01.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.xsdat the end of the value of xsi:schemaLocationin order to refer to the local hard drive. I found this method, here:
所以,如果你比较与上面提到的例子中,新的XML内容,我添加的唯一的事情就是文件:///home/train/Documents/myutl_file_dir/Example-01.xsd在值的末尾XSI:的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 只是忽略了我为架构文件定义的文件路径,它认为没有为此 XML 文档声明任何架构。
Any idea? How can I deal with this problem?
任何的想法?我该如何处理这个问题?
Thanks in advance,
提前致谢,
Dariyoosh
达里约什
采纳答案by dariyoosh
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/prodrefers 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 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
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:
- the value of the target namespace declared in the XML schema
- the schema location hint, the unique identifier passed to procedure DBMS_XMLSCHEMA.registerSchema when the schema is registered with the database
如果目标 XML 模式声明了目标命名空间,则 schemaLocation 属性用于标识 XML 模式。该属性的值是一对用空格分隔的值:
- XML 模式中声明的目标命名空间的值
- 模式位置提示,当模式注册到数据库时传递给过程 DBMS_XMLSCHEMA.registerSchema 的唯一标识符
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.xsd 的文件中,然后提供该文档的文件 URL,file:///home/train/Documents/myutl_file_dir /Example-01.xsd. 这确实是一件愚蠢的事情,因为当您通过调用 DBMS_XMLSchema.registerSchema 向 oracle 注册模式时,oracle 会注册 XML 模式文档的内容。所以oracle 需要的是在注册期间使用的schemaURL,它允许唯一地查找和识别特定的schema。这正是我的错误,我认为 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
达里约什
回答by stefannebesnak
The method can be invoked on only schema basedxmltype objects.
该方法只能在基于模式的xmltype 对象上调用。
Try delete and reload documents, before registering an XML schema they reference.
在注册文档引用的 XML 模式之前,尝试删除并重新加载文档。
Oracle XML DB Developer's Guide:
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.
You must delete such instance documents, and reload them after registering the schema, in order to obtain schema-based documents.
注册 XML 模式时,请记住,注册模式的行为不会影响已加载到引用 XML 模式的 Oracle XML DB 信息库中的任何实例文档的状态。由于 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 引用)