If you want to create valid XML, use the DOM Extension. This way you don't have to bother about any Regex. If you try to put in an invalid name to a DomElement, you'll get an error.
function isValidXmlName($name)
{
try {
new DOMElement($name);
return TRUE;
} catch(DOMException $e) {
return FALSE;
}
}
This will give
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
and is likely good enough for what you want to do.
Pedantic note 1
Note the distinction between localName and QName. ext/dom assumes you are using a namespaced element if there is a prefix before the colon, which adds constraints to how the name may be formed. Technically, b:b is a valid local name though because NameStartChar is part of NameChar. If you want to include these, change the function to
function isValidXmlName($name)
{
try {
new DOMElement(
$name,
null,
strpos($name, ':') >= 1 ? 'http://example.com' : null
);
return TRUE;
} catch(DOMException $e) {
return FALSE;
}
}
Pedantic note 2
Note that elements may start with "xml". W3schools (who is not affiliated with the W3c) apparently got this part wrong (wouldn't be the first time). If you really want to exclude elements starting with xml add
if(stripos($name, 'xml') === 0) return false;
before the try/catch
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…