我需要PHP中的regex或函数来验证字符串是一个好的XML元素名称。
表格w3schools:
XML元素必须遵循以下命名规则:
我可以编写一个基本的正则表达式,它将检查规则1、2和4,但它不会考虑所有允许的标点符号,也不会考虑第3条规则。
\w[\w0-9-]友好更新
这里是格式良好的XML元素名称的更权威的来源
名称和标记
NameStartChar ::=
":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] |
[#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] |
[#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] |
[#x10000-#xEFFFF]
NameChar ::=
NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
Name ::=
NameStartChar (NameChar)*另外,还指定了一个单独的非令牌化规则:
以字符串"xml“开头的名称,或以任何与之匹配的字符串((‘X’分部‘x’)(‘M’区‘m’‘)(’L‘=’l‘’))开头的名称,都保留在本规范或未来版本的规范中用于标准化。
发布于 2010-03-25 22:36:00
怎么样
/\A(?!XML)[a-z][\w0-9-]*/i用法:
if (preg_match('/\A(?!XML)[a-z][\w0-9-]*/i', $subject)) {
# valid name
} else {
# invalid name
}解释:
\A Beginning of the string
(?!XML) Negative lookahead (assert that it is impossible to match "XML")
[a-z] Match a non-digit, non-punctuation character
[\w0-9-]* Match an arbitrary number of allowed characters
/i make the whole thing case-insensitive发布于 2010-03-25 22:36:10
如果要创建有效XML,请使用DOM扩展。这样你就不用担心任何Regex了。如果您试图将一个无效的名称输入到一个DomElement中,您将得到一个错误。
function isValidXmlName($name)
{
try {
new DOMElement($name);
return TRUE;
} catch(DOMException $e) {
return FALSE;
}
}这会给
var_dump( isValidXmlName('foo') ); // true valid localName
var_dump( isValidXmlName(':foo') ); // true valid localName
var_dump( isValidXmlName(':b:c') ); // true valid localName
var_dump( isValidXmlName('b:c') ); // false assumes QName很可能对你想做的事来说已经足够了。
书呆子音符1
注意localName和QName之间的区别。ext/dom假设您使用的是名称空间元素,如果冒号前面有前缀,这将为名称的形成添加约束。从技术上讲,b:b是一个有效的本地名称,因为NameStartChar是NameChar的一部分。如果要包含这些内容,请将该函数更改为
function isValidXmlName($name)
{
try {
new DOMElement(
$name,
null,
strpos($name, ':') >= 1 ? 'http://example.com' : null
);
return TRUE;
} catch(DOMException $e) {
return FALSE;
}
}书呆子音符2
请注意,元素可以以"xml“开头。W3schools (他不属于W3c)显然搞错了这个部分(不会是第一次)。如果确实希望排除以xml开头的元素,请添加
if(stripos($name, 'xml') === 0) return false;在try/catch之前。
发布于 2013-03-03 17:58:55
到目前为止,这一点已经被忽略了,尽管问题是旧的:通过PHP的pcre函数进行名称验证,这些函数是用XML规范简化的。
XML的定义非常清楚地说明了它的规范(可扩展标记语言(XML) 1.0 (第五版))中的元素名称:
[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
[5] Name ::= NameStartChar (NameChar)*可以将此表示法转换为与preg_match兼容的UTF-8正则表达式,这里作为单引号的PHP字符串逐字复制:
'~^[:A-Z_a-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}][:A-Z_a-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}.\\-0-9\\xB7\\x{0300}-\\x{036F}\\x{203F}-\\x{2040}]*$~u'或者作为另一个以更易读的方式命名子模式的变体:
'~
# XML 1.0 Name symbol PHP PCRE regex <http://www.w3.org/TR/REC-xml/#NT-Name>
(?(DEFINE)
(?<NameStartChar> [:A-Z_a-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}])
(?<NameChar> (?&NameStartChar) | [.\\-0-9\\xB7\\x{0300}-\\x{036F}\\x{203F}-\\x{2040}])
(?<Name> (?&NameStartChar) (?&NameChar)*)
)
^(?&Name)$
~ux'请注意,此模式包含冒号:,您可能希望排除它(第一种模式中的两种形式,第二种模式中的一种),因为XML验证原因(例如,对NCName的测试)。
用法示例:
$name = '::...';
$pattern = '~
# XML 1.0 Name symbol PHP PCRE regex <http://www.w3.org/TR/REC-xml/#NT-Name>
(?(DEFINE)
(?<NameStartChar> [:A-Z_a-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}])
(?<NameChar> (?&NameStartChar) | [.\\-0-9\\xB7\\x{0300}-\\x{036F}\\x{203F}-\\x{2040}])
(?<Name> (?&NameStartChar) (?&NameChar)*)
)
^(?&Name)$
~ux';
$valid = 1 === preg_match($pattern, $name); # bool(true)以XML开头的元素名称(小写或大写字母)是不可能的,这是不正确的。<XML/>是一个格式非常好的XML,而XML是一个格式非常好的元素名称。
只是这些名称位于格式良好的元素名称的子集中,这些元素名称是为标准化而保留的(XMLVersion1.0和更高版本)。很容易测试(格式良好的)元素名称是否通过字符串比较保留:
$reserved = $valid && 0 === stripos($name, 'xml'));或者另一个正则表达式:
$reserved = $valid && 1 === preg_match('~^[Xx][Mm][Ll]~', $name);DOMDocument不能测试保留的名称,至少我不知道怎么做,我一直在寻找。
一个有效的元素名称需要一个唯一的元素类型声明,这个声明似乎不在这里讨论的范围之内,因为没有提供这样的声明。因此,答案并没有考虑到这一点。如果有一个元素类型声明,您只需要根据所有(区分大小写的)名称的白列表进行验证,因此这将是一个简单的区分大小写的字符串比较。
游走:DOMDocument与正则表达式有什么不同?
与DOMDocument / DOMElement相比,对有效元素名的限定有一些不同之处。DOM扩展处于某种混合模式,这使得它无法预测它验证的内容。下面的偏移说明了这种行为,并说明了如何控制它。
让我们接受$name并实例化一个元素:
$element = new DOMElement($name);结果取决于:
因此,第一个字符决定比较模式。
正则表达式专门编写了要检查的内容,这里是XML1.0 Name符号。
您可以通过用冒号前缀名称来实现DOMElement的相同目标:
function isValidXmlName($name)
{
try {
new DOMElement(":$name");
return TRUE;
} catch (DOMException $e) {
return FALSE;
}
}要显式检查QName,可以通过将其转换为PrefixedName来实现,以防它是UnprefixedName
function isValidXmlnsQname($qname)
{
$prefixedName = (!strpos($qname, ':') ? 'prefix:' : '') . $qname;
try {
new DOMElement($prefixedName, NULL, 'uri:ns');
return TRUE;
} catch (DOMException $e) {
return FALSE;
}
}https://stackoverflow.com/questions/2519845
复制相似问题