Oracle XML 架构验证日期模式错误
Oracle XML Schema Validation date pattern error
我正在尝试用 XSD 验证 XML。但它会抛出一个关于日期格式的奇怪错误:
[1]: LSX-00333: literal "2016-05-26T16:37:42.000000" is not valid with respect to the pattern
然而,这就是我 XML 中的内容:
<?xml version="1.0" encoding="UTF-8"?>
<root DataFeed="2016-04"
VersionXSD="2.0"
Currency="USD"
DataProcessDate="2016-05-26T16:37:42"
xmlns="http://www.millicom.com">
我的 XSD:
<xs:attribute name="DataProcessDate"
use="required"
type="DateTimeType"/>
<xs:simpleType name="DateTimeType">
<xs:restriction base="xs:dateTime">
<xs:pattern value=".+(\-10:00|\-09:00|\-08:00|\-07:00|\-06:00|\-05:00|\-04:00|\+00:00|Z|-04:00)"/>
</xs:restriction>
</xs:simpleType>
这是我的代码:
DECLARE
v_schema_url VARCHAR2 (200) := 'MyFact.xsd';
v_blob BLOB;
v_clob CLOB;
v_xml XMLTYPE;
xml_file BFILE;
xmlClob CLOB;
src_offset number := 1 ;
dest_offset number := 1 ;
lang_ctx number := DBMS_LOB.DEFAULT_LANG_CTX;
warning integer;
res integer;
BEGIN
dbms_xmlschema.deleteschema(v_schema_url);
DBMS_XMLSCHEMA.registerschema (schemaurl => v_schema_url,
schemadoc => bfilename ('DIR_XSD','MyFact.xsd'),
local => TRUE);
xml_file := BFILENAME('DIR_XSD', 'Test.xml');
DBMS_LOB.CREATETEMPORARY(xmlClob, true);
DBMS_LOB.FILEOPEN(xml_file, DBMS_LOB.FILE_READONLY);
DBMS_LOB.LOADCLOBFROMFILE(xmlClob, xml_file, DBMS_LOB.LOBMAXSIZE, src_offset,
dest_offset, DBMS_LOB.DEFAULT_CSID, lang_ctx, warning);
v_xml := XMLType.createXML(xmldata=>xmlClob,schema=>v_schema_url);
DBMS_LOB.FILECLOSEALL();
DBMS_LOB.FREETEMPORARY(xmlClob);
v_xml.schemaValidate();
IF v_xml.isschemavalid (v_schema_url) = 1 THEN
DBMS_OUTPUT.put_line ('valid');
ELSE
DBMS_OUTPUT.put_line ('not valid');
END IF;
END;
出于某种原因,它添加了微秒并且未通过模式检查。我怎样才能避免这种情况?
我想要的行为是正确执行并输出 "valid"
你可能在做这样的事情。
我假设你的数据类型是这样声明的。
<xs:simpleType name="DataProcessDateType">
<xs:restriction base="xs:dateTime">
<xs:pattern value="\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}"/>
</xs:restriction>
</xs:simpleType>
这里发生了什么。
1) 2016-05-26T16:37:42
字符串被转换为 xs:dataTime 并且看起来像
2016-05-26T16:37:42.000000
.
2) 接下来 xsd 是托盘匹配 2016-05-26T16:37:42.000000
到模式 "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}"
但模式没有尾随零。并引发 LSX-00333 错误。
你能做什么。
- (1- 选项)在模式
"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}"
中包含尾随零
(2 - 选项) 从类型中删除 xs:pattern;
xsd clob := q'~<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="DataFeed"/>
<xs:attribute type="xs:float" name="VersionXSD"/>
<xs:attribute type="xs:string" name="Currency"/>
<xs:attribute type="DataProcessDateType" name="DataProcessDate"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:simpleType name="DataProcessDateType">
<xs:restriction base="xs:dateTime">
<xs:pattern value="\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>~';
begin
DBMS_XMLSCHEMA.registerschema (schemaurl => 'test_xsd',
schemadoc => xmltype(xsd),
local => TRUE);
end;
-- exec dbms_XMLSCHEMA.deleteSchema(schemaurl => 'test_xsd') ;
宣布
vxml xmltype := xmltype(q'~~');
begin
vxml := vxml.createschemabasedxml('test_xsd');
vxml.schemaValidate();
IF vxml.isschemavalid ('test_xsd') = 1 THEN
DBMS_OUTPUT.put_line ('valid');
ELSE
DBMS_OUTPUT.put_line ('not valid');
END IF;
end;
虽然您没有向我们展示您的数据类型定义,但我的第一直觉是 Oracle 对规范的解释不正确。我个人认为使用非字符串数据类型的模式是非常值得怀疑的,但规范非常清楚(第 2 部分,§4.1.4,验证规则数据类型有效)应该使用模式方面来匹配中写入的值源文档(在 whitespace 规范化之后)称为 "a literal in the lexical space",然后将其转换为值 space,其中评估其他方面,例如 minInclusive 和枚举。我的印象是 Oracle 取而代之的是词法值,将其转换为值 space,然后根据模式测试值的规范词法形式。但这也不对,因为规范的词法形式不能在小数秒部分包含尾随零(参见 3.2.7.2)。
我正在尝试用 XSD 验证 XML。但它会抛出一个关于日期格式的奇怪错误:
[1]: LSX-00333: literal "2016-05-26T16:37:42.000000" is not valid with respect to the pattern
然而,这就是我 XML 中的内容:
<?xml version="1.0" encoding="UTF-8"?>
<root DataFeed="2016-04"
VersionXSD="2.0"
Currency="USD"
DataProcessDate="2016-05-26T16:37:42"
xmlns="http://www.millicom.com">
我的 XSD:
<xs:attribute name="DataProcessDate"
use="required"
type="DateTimeType"/>
<xs:simpleType name="DateTimeType">
<xs:restriction base="xs:dateTime">
<xs:pattern value=".+(\-10:00|\-09:00|\-08:00|\-07:00|\-06:00|\-05:00|\-04:00|\+00:00|Z|-04:00)"/>
</xs:restriction>
</xs:simpleType>
这是我的代码:
DECLARE
v_schema_url VARCHAR2 (200) := 'MyFact.xsd';
v_blob BLOB;
v_clob CLOB;
v_xml XMLTYPE;
xml_file BFILE;
xmlClob CLOB;
src_offset number := 1 ;
dest_offset number := 1 ;
lang_ctx number := DBMS_LOB.DEFAULT_LANG_CTX;
warning integer;
res integer;
BEGIN
dbms_xmlschema.deleteschema(v_schema_url);
DBMS_XMLSCHEMA.registerschema (schemaurl => v_schema_url,
schemadoc => bfilename ('DIR_XSD','MyFact.xsd'),
local => TRUE);
xml_file := BFILENAME('DIR_XSD', 'Test.xml');
DBMS_LOB.CREATETEMPORARY(xmlClob, true);
DBMS_LOB.FILEOPEN(xml_file, DBMS_LOB.FILE_READONLY);
DBMS_LOB.LOADCLOBFROMFILE(xmlClob, xml_file, DBMS_LOB.LOBMAXSIZE, src_offset,
dest_offset, DBMS_LOB.DEFAULT_CSID, lang_ctx, warning);
v_xml := XMLType.createXML(xmldata=>xmlClob,schema=>v_schema_url);
DBMS_LOB.FILECLOSEALL();
DBMS_LOB.FREETEMPORARY(xmlClob);
v_xml.schemaValidate();
IF v_xml.isschemavalid (v_schema_url) = 1 THEN
DBMS_OUTPUT.put_line ('valid');
ELSE
DBMS_OUTPUT.put_line ('not valid');
END IF;
END;
出于某种原因,它添加了微秒并且未通过模式检查。我怎样才能避免这种情况? 我想要的行为是正确执行并输出 "valid"
你可能在做这样的事情。 我假设你的数据类型是这样声明的。
<xs:simpleType name="DataProcessDateType">
<xs:restriction base="xs:dateTime">
<xs:pattern value="\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}"/>
</xs:restriction>
</xs:simpleType>
这里发生了什么。
1)
2016-05-26T16:37:42
字符串被转换为 xs:dataTime 并且看起来像2016-05-26T16:37:42.000000
.2) 接下来 xsd 是托盘匹配
2016-05-26T16:37:42.000000
到模式"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}"
但模式没有尾随零。并引发 LSX-00333 错误。
你能做什么。
- (1- 选项)在模式
"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}"
中包含尾随零
(2 - 选项) 从类型中删除 xs:pattern;
xsd clob := q'~<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="root"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="DataFeed"/> <xs:attribute type="xs:float" name="VersionXSD"/> <xs:attribute type="xs:string" name="Currency"/> <xs:attribute type="DataProcessDateType" name="DataProcessDate"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:simpleType name="DataProcessDateType"> <xs:restriction base="xs:dateTime"> <xs:pattern value="\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}"/> </xs:restriction> </xs:simpleType> </xs:schema>~'; begin DBMS_XMLSCHEMA.registerschema (schemaurl => 'test_xsd', schemadoc => xmltype(xsd), local => TRUE); end;
-- exec dbms_XMLSCHEMA.deleteSchema(schemaurl => 'test_xsd') ; 宣布 vxml xmltype := xmltype(q'~~');
begin vxml := vxml.createschemabasedxml('test_xsd'); vxml.schemaValidate(); IF vxml.isschemavalid ('test_xsd') = 1 THEN DBMS_OUTPUT.put_line ('valid'); ELSE DBMS_OUTPUT.put_line ('not valid'); END IF; end;
虽然您没有向我们展示您的数据类型定义,但我的第一直觉是 Oracle 对规范的解释不正确。我个人认为使用非字符串数据类型的模式是非常值得怀疑的,但规范非常清楚(第 2 部分,§4.1.4,验证规则数据类型有效)应该使用模式方面来匹配中写入的值源文档(在 whitespace 规范化之后)称为 "a literal in the lexical space",然后将其转换为值 space,其中评估其他方面,例如 minInclusive 和枚举。我的印象是 Oracle 取而代之的是词法值,将其转换为值 space,然后根据模式测试值的规范词法形式。但这也不对,因为规范的词法形式不能在小数秒部分包含尾随零(参见 3.2.7.2)。