首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正则表达式可以正常工作,但放在XML架构中时会失败

正则表达式可以正常工作,但放在XML架构中时会失败
EN

Stack Overflow用户
提问于 2010-05-11 04:54:56
回答 2查看 671关注 0票数 2

我有一个简单的doc.xml文件,它包含一个带有时间戳属性的根元素:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<root Timestamp="04-21-2010 16:00:19.000" />

我想根据我的简单schema.xsd验证这个文档,以确保时间戳的格式是正确的:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="root">
    <xs:complexType>
      <xs:attribute name="Timestamp" use="required" type="timeStampType"/>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="timeStampType">
    <xs:restriction base="xs:string">
      <xs:pattern value="(0[0-9]{1})|(1[0-2]{1})-(3[0-1]{1}|[0-2]{1}[0-9]{1})-[2-9]{1}[0-9]{3} ([0-1]{1}[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}.[0-9]{3}" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

因此,我使用lxml Python模块并尝试执行一个简单的模式验证并报告任何错误:

代码语言:javascript
复制
from lxml import etree

schema = etree.XMLSchema( etree.parse("schema.xsd") )
doc = etree.parse("doc.xml")

if not schema.validate(doc):
    for e in schema.error_log:
        print e.message

我的XML文档验证失败,并显示以下错误消息:

代码语言:javascript
复制
Element 'root', attribute 'Timestamp': [facet 'pattern'] The value '04-21-2010 16:00:19.000' is not accepted by the pattern '(0[0-9]{1})|(1[0-2]{1})-(3[0-1]{1}|[0-2]{1}[0-9]{1})-[2-9]{1}[0-9]{3} ([0-1]{1}[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}.[0-9]{3}'.
Element 'root', attribute 'Timestamp': '04-21-2010 16:00:19.000' is not a valid value of the atomic type 'timeStampType'.

所以看起来我的正则表达式一定是有问题的。但是当我尝试在命令行验证正则表达式时,它通过:

代码语言:javascript
复制
>>> import re
>>> pat = '(0[0-9]{1})|(1[0-2]{1})-(3[0-1]{1}|[0-2]{1}[0-9]{1})-[2-9]{1}[0-9]{3} ([0-1]{1}[0-9]{1}|2[0-3]{1}):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}.[0-9]{3}'
>>> assert re.match(pat, '04-21-2010 16:00:19.000')
>>> 

我知道XSD正则表达式并不具备所有功能,但the documentation I've found指出我使用的每个功能都应该有效。

那么,我误解了什么,为什么我的文档失败了?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-05-11 05:05:29

你的|匹配范围比你想象的要大。

代码语言:javascript
复制
(0[0-9]{1})|(1[0-2]{1})-(3[0-1]{1}|[0-2]{1}[0-9]{1})-[2-9]{1}[0-9]{3}

解析为:

代码语言:javascript
复制
(0[0-9]{1})
    -or-
(1[0-2]{1})-(3[0-1]{1}|[0-2]{1}[0-9]{1})-[2-9]{1}[0-9]{3}

如果你想避免它,你需要使用更多的分组;

代码语言:javascript
复制
((0[0-9]{1})|(1[0-2]{1}))-((3[0-1]{1}|[0-2]{1}[0-9]{1}))-[2-9]{1}[0-9]{3} (([0-1]{1}[0-9]{1}|2[0-3]{1})):[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}.[0-9]{3}
票数 3
EN

Stack Overflow用户

发布于 2010-05-11 05:06:19

该表达式有几个错误。

当有效的month.

  • A|BCABC匹配,而不是ACBC匹配时,您允许00。因此,以(0[0-9]{1})|开头的表达式可以匹配任何包含0009的字符串。你想要的是只通过12匹配01,后面跟着一个破折号。

  • 你允许00作为有效的日期。

  • 模式不锚定在文本的开头和结尾-添加^和<00>d22>。这就是使用Python测试成功的原因。

顺便说一下,你为什么不使用xs:dateTime呢?它有一个非常相似的格式--我想是yyyy-mm-ddThh:mm:ss.fff

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2806399

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档