зеркало из https://github.com/mozilla/gecko-dev.git
[NPOTDB] Add support for missing built-in derived schemas. Bug 345907, patch by sspeiche, r=doronr
This commit is contained in:
Родитель
ff0005f41e
Коммит
8695ecb64f
|
@ -716,6 +716,25 @@ nsSchemaValidator::ValidateDerivedBuiltinType(const nsAString & aNodeValue,
|
|||
break;
|
||||
}
|
||||
|
||||
/* http://w3.org/TR/xmlschema-2/#nonNegativeInteger */
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER: {
|
||||
if (aDerived->minExclusive.value.IsEmpty()) {
|
||||
aDerived->minExclusive.value.AssignLiteral("-1");
|
||||
} else if (aDerived->minInclusive.value.IsEmpty()) {
|
||||
aDerived->minInclusive.value.AssignLiteral("0");
|
||||
}
|
||||
|
||||
rv = ValidateBuiltinTypeInteger(aNodeValue,
|
||||
aDerived->totalDigits.value,
|
||||
aDerived->maxExclusive.value,
|
||||
aDerived->minExclusive.value,
|
||||
aDerived->maxInclusive.value,
|
||||
aDerived->minInclusive.value,
|
||||
&aDerived->enumerationList,
|
||||
&isValid);
|
||||
break;
|
||||
}
|
||||
|
||||
/* http://www.w3.org/TR/xmlschema-2/#negativeInteger */
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER: {
|
||||
if (aDerived->maxExclusive.value.IsEmpty()) {
|
||||
|
@ -999,6 +1018,105 @@ nsSchemaValidator::ValidateDerivedBuiltinType(const nsAString & aNodeValue,
|
|||
&isValid);
|
||||
break;
|
||||
}
|
||||
/* http://www.w3.org/TR/xmlschema-2/#name */
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NAME: {
|
||||
if (nsSchemaValidatorUtils::IsValidSchemaName(aNodeValue)) {
|
||||
rv = ValidateBuiltinTypeString(aNodeValue,
|
||||
aDerived->length.value,
|
||||
aDerived->length.isDefined,
|
||||
aDerived->minLength.value,
|
||||
aDerived->minLength.isDefined,
|
||||
aDerived->maxLength.value,
|
||||
aDerived->maxLength.isDefined,
|
||||
&aDerived->enumerationList,
|
||||
&isValid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME: {
|
||||
if (nsSchemaValidatorUtils::IsValidSchemaNCName(aNodeValue)) {
|
||||
rv = ValidateBuiltinTypeString(aNodeValue,
|
||||
aDerived->length.value,
|
||||
aDerived->length.isDefined,
|
||||
aDerived->minLength.value,
|
||||
aDerived->minLength.isDefined,
|
||||
aDerived->maxLength.value,
|
||||
aDerived->maxLength.isDefined,
|
||||
&aDerived->enumerationList,
|
||||
&isValid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_ID: {
|
||||
if (nsSchemaValidatorUtils::IsValidSchemaID(aNodeValue)) {
|
||||
rv = ValidateBuiltinTypeString(aNodeValue,
|
||||
aDerived->length.value,
|
||||
aDerived->length.isDefined,
|
||||
aDerived->minLength.value,
|
||||
aDerived->minLength.isDefined,
|
||||
aDerived->maxLength.value,
|
||||
aDerived->maxLength.isDefined,
|
||||
&aDerived->enumerationList,
|
||||
&isValid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF: {
|
||||
if (nsSchemaValidatorUtils::IsValidSchemaIDRef(aNodeValue)) {
|
||||
rv = ValidateBuiltinTypeString(aNodeValue,
|
||||
aDerived->length.value,
|
||||
aDerived->length.isDefined,
|
||||
aDerived->minLength.value,
|
||||
aDerived->minLength.isDefined,
|
||||
aDerived->maxLength.value,
|
||||
aDerived->maxLength.isDefined,
|
||||
&aDerived->enumerationList,
|
||||
&isValid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS: {
|
||||
if (nsSchemaValidatorUtils::IsValidSchemaIDRefs(aNodeValue)) {
|
||||
rv = ValidateBuiltinTypeString(aNodeValue,
|
||||
aDerived->length.value,
|
||||
aDerived->length.isDefined,
|
||||
aDerived->minLength.value,
|
||||
aDerived->minLength.isDefined,
|
||||
aDerived->maxLength.value,
|
||||
aDerived->maxLength.isDefined,
|
||||
&aDerived->enumerationList,
|
||||
&isValid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN: {
|
||||
if (nsSchemaValidatorUtils::IsValidSchemaNMToken(aNodeValue)) {
|
||||
rv = ValidateBuiltinTypeString(aNodeValue,
|
||||
aDerived->length.value,
|
||||
aDerived->length.isDefined,
|
||||
aDerived->minLength.value,
|
||||
aDerived->minLength.isDefined,
|
||||
aDerived->maxLength.value,
|
||||
aDerived->maxLength.isDefined,
|
||||
&aDerived->enumerationList,
|
||||
&isValid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS: {
|
||||
if (nsSchemaValidatorUtils::IsValidSchemaNMTokens(aNodeValue)) {
|
||||
rv = ValidateBuiltinTypeString(aNodeValue,
|
||||
aDerived->length.value,
|
||||
aDerived->length.isDefined,
|
||||
aDerived->minLength.value,
|
||||
aDerived->minLength.isDefined,
|
||||
aDerived->maxLength.value,
|
||||
aDerived->maxLength.isDefined,
|
||||
&aDerived->enumerationList,
|
||||
&isValid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
rv = NS_ERROR_SCHEMAVALIDATOR_TYPE_NOT_FOUND;
|
||||
|
@ -1148,6 +1266,16 @@ nsSchemaValidator::ValidateBuiltinType(const nsAString & aNodeValue,
|
|||
break;
|
||||
}
|
||||
|
||||
/* http://w3.org/TR/xmlschema-2/#nonNegativeInteger */
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER: {
|
||||
// nonNegativeInteger inherits from integer, with minInclusive
|
||||
// being 0 (only positive integers)
|
||||
ValidateBuiltinTypeInteger(aNodeValue, nsnull, EmptyString(),
|
||||
EmptyString(), EmptyString(),
|
||||
NS_LITERAL_STRING("0"), nsnull, &isValid);
|
||||
break;
|
||||
}
|
||||
|
||||
/* http://www.w3.org/TR/xmlschema-2/#negativeInteger */
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER: {
|
||||
// negativeInteger inherits from integer, with maxInclusive
|
||||
|
@ -1288,6 +1416,35 @@ nsSchemaValidator::ValidateBuiltinType(const nsAString & aNodeValue,
|
|||
isValid = IsValidSchemaQName(aNodeValue);
|
||||
break;
|
||||
}
|
||||
/* http://www.w3.org/TR/xmlschema-2/#name */
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NAME: {
|
||||
isValid = nsSchemaValidatorUtils::IsValidSchemaName(aNodeValue);
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME: {
|
||||
isValid = nsSchemaValidatorUtils::IsValidSchemaNCName(aNodeValue);
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_ID: {
|
||||
isValid = nsSchemaValidatorUtils::IsValidSchemaID(aNodeValue);
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_IDREF: {
|
||||
isValid = nsSchemaValidatorUtils::IsValidSchemaIDRef(aNodeValue);
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS: {
|
||||
isValid = nsSchemaValidatorUtils::IsValidSchemaIDRefs(aNodeValue);
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN: {
|
||||
isValid = nsSchemaValidatorUtils::IsValidSchemaNMToken(aNodeValue);
|
||||
break;
|
||||
}
|
||||
case nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS: {
|
||||
isValid = nsSchemaValidatorUtils::IsValidSchemaNMTokens(aNodeValue);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
rv = NS_ERROR_SCHEMAVALIDATOR_TYPE_NOT_FOUND;
|
||||
|
|
|
@ -1413,6 +1413,179 @@ nsSchemaValidatorUtils::IsValidSchemaLanguage(const nsAString &aStrValue)
|
|||
return isValid;
|
||||
}
|
||||
|
||||
// http://www.w3.org/TR/xmlschema-2/#name
|
||||
PRBool
|
||||
nsSchemaValidatorUtils::IsValidSchemaName(const nsAString &aStrValue)
|
||||
{
|
||||
PRBool isValid = PR_FALSE;
|
||||
|
||||
// xsd:Name is restriction on xsd:token
|
||||
if (IsValidSchemaToken(aStrValue)) {
|
||||
/* http://www.w3.org/TR/2000/WD-xml-2e-20000814
|
||||
[4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
|
||||
CombiningChar | Extender
|
||||
[5] Name ::= (Letter | '_' | ':') ( NameChar)*
|
||||
*/
|
||||
// XXX Need to handling CombiningChar and Extender as well
|
||||
// XXX Additional Unicode testing needed?
|
||||
nsAutoString pattern;
|
||||
pattern.AssignLiteral("^[a-zA-Z_:][\\w\\.\\-:]*$");
|
||||
nsCOMPtr<nsISchemaValidatorRegexp> regexp = do_GetService(kREGEXP_CID);
|
||||
nsresult rv = regexp->RunRegexp(aStrValue, pattern, "g", &isValid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// http://www.w3.org/TR/xmlschema-2/#ncname
|
||||
PRBool
|
||||
nsSchemaValidatorUtils::IsValidSchemaNCName(const nsAString &aStrValue)
|
||||
{
|
||||
PRBool isValid = PR_FALSE;
|
||||
|
||||
// xsd:NCNAME is a restriction on xsd:Name
|
||||
if (IsValidSchemaToken(aStrValue)) {
|
||||
/* http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName
|
||||
NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
|
||||
CombiningChar | Extender
|
||||
NCName ::= (Letter | '_') (NCNameChar)*
|
||||
*/
|
||||
nsAutoString pattern;
|
||||
// XXX Need to handle Combining|Extender and Unicode Letters
|
||||
// xsd:Name minus the ":"
|
||||
pattern.AssignLiteral("^[a-zA-Z_][\\w\\.\\-]*$");
|
||||
nsCOMPtr<nsISchemaValidatorRegexp> regexp = do_GetService(kREGEXP_CID);
|
||||
nsresult rv = regexp->RunRegexp(aStrValue, pattern, "g", &isValid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// http://www.w3.org/TR/xmlschema-2/#id
|
||||
PRBool
|
||||
nsSchemaValidatorUtils::IsValidSchemaID(const nsAString &aStrValue)
|
||||
{
|
||||
PRBool isValid = PR_FALSE;
|
||||
|
||||
// xsd:ID is a restriction of xsd:NCNAME
|
||||
if (IsValidSchemaNCName(aStrValue)) {
|
||||
isValid = PR_TRUE;
|
||||
// XXX Uniqueness tests per
|
||||
// http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-TokenizedType
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// http://www.w3.org/TR/xmlschema-2/#idref
|
||||
PRBool
|
||||
nsSchemaValidatorUtils::IsValidSchemaIDRef(const nsAString &aStrValue)
|
||||
{
|
||||
PRBool isValid = PR_FALSE;
|
||||
|
||||
// xsd:IDREF is a restriction of xsd:NCName
|
||||
if (IsValidSchemaNCName(aStrValue)) {
|
||||
isValid = PR_TRUE;
|
||||
// XXX Ensure IDREF really references an ID,
|
||||
// http://www.w3.org/TR/2000/WD-xml-2e-20000814#idref
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// http://www.w3.org/TR/xmlschema-2/#idrefs
|
||||
PRBool
|
||||
nsSchemaValidatorUtils::IsValidSchemaIDRefs(const nsAString &aStrValue)
|
||||
{
|
||||
PRBool isValid = PR_FALSE;
|
||||
|
||||
// Need to validate each IDREF
|
||||
nsAString::const_iterator iter, end, tokenStart;
|
||||
nsAutoString idref;
|
||||
aStrValue.BeginReading(iter);
|
||||
aStrValue.BeginReading(tokenStart);
|
||||
aStrValue.EndReading(end);
|
||||
while (iter != end) {
|
||||
for (;IsWhitespace(*iter) && iter != end; ++iter);
|
||||
tokenStart = iter;
|
||||
|
||||
// Find end of token
|
||||
for (;!IsWhitespace(*iter) && iter != end; ++iter);
|
||||
|
||||
// Get the token/idref and validate
|
||||
idref = Substring(tokenStart, iter);
|
||||
isValid = IsValidSchemaIDRef(idref);
|
||||
if (!isValid) break; // No need to continue
|
||||
|
||||
if (iter != end) ++iter;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSchemaValidatorUtils::IsWhitespace(PRUnichar aChar)
|
||||
{
|
||||
return aChar == ' ' || aChar == '\t' || aChar == '\n' ||
|
||||
aChar == '\r' || aChar == '\v';
|
||||
}
|
||||
|
||||
// http://www.w3.org/TR/xmlschema-2/#nmtoken
|
||||
PRBool
|
||||
nsSchemaValidatorUtils::IsValidSchemaNMToken(const nsAString &aStrValue)
|
||||
{
|
||||
PRBool isValid = PR_FALSE;
|
||||
|
||||
// xsd:NMTOKEN is a restriction on xsd:token
|
||||
if (IsValidSchemaToken(aStrValue)) {
|
||||
/*
|
||||
NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
|
||||
CombiningChar | Extender
|
||||
Nmtoken ::= (NameChar)+
|
||||
*/
|
||||
nsAutoString pattern;
|
||||
// XXX Need to handle Combining|Extender and possibly unicode letters
|
||||
pattern.AssignLiteral("^[\\w\\.\\-_:]*$");
|
||||
nsCOMPtr<nsISchemaValidatorRegexp> regexp = do_GetService(kREGEXP_CID);
|
||||
nsresult rv = regexp->RunRegexp(aStrValue, pattern, "g", &isValid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// http://www.w3.org/TR/xmlschema-2/#nmtokens
|
||||
PRBool
|
||||
nsSchemaValidatorUtils::IsValidSchemaNMTokens(const nsAString &aStrValue)
|
||||
{
|
||||
PRBool isValid = PR_FALSE;
|
||||
|
||||
// Need to validate each NNTOKEN
|
||||
nsAString::const_iterator iter, end, tokenStart;
|
||||
nsAutoString idref;
|
||||
aStrValue.BeginReading(iter);
|
||||
aStrValue.BeginReading(tokenStart);
|
||||
aStrValue.EndReading(end);
|
||||
while (iter != end) {
|
||||
for (;IsWhitespace(*iter) && iter != end; ++iter);
|
||||
tokenStart = iter;
|
||||
|
||||
// Find end of token
|
||||
for (;!IsWhitespace(*iter) && iter != end; ++iter);
|
||||
|
||||
// Get the token/idref and validate
|
||||
idref = Substring(tokenStart, iter);
|
||||
isValid = IsValidSchemaNMToken(idref);
|
||||
if (!isValid) break; // No need to continue
|
||||
|
||||
if (iter != end) ++iter;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSchemaValidatorUtils::HandleEnumeration(const nsAString &aStrValue,
|
||||
const nsStringArray &aEnumerationList)
|
||||
|
|
|
@ -218,6 +218,14 @@ public:
|
|||
static PRBool IsValidSchemaNormalizedString(const nsAString & aStrValue);
|
||||
static PRBool IsValidSchemaToken(const nsAString & aStrValue);
|
||||
static PRBool IsValidSchemaLanguage(const nsAString & aStrValue);
|
||||
static PRBool IsValidSchemaName(const nsAString & aStrValue);
|
||||
static PRBool IsValidSchemaNCName(const nsAString & aStrValue);
|
||||
static PRBool IsValidSchemaNMToken(const nsAString & aStrValue);
|
||||
static PRBool IsValidSchemaNMTokens(const nsAString & aStrValue);
|
||||
static PRBool IsValidSchemaID(const nsAString & aStrValue);
|
||||
static PRBool IsValidSchemaIDRef(const nsAString & aStrValue);
|
||||
static PRBool IsValidSchemaIDRefs(const nsAString & aStrValue);
|
||||
static PRBool IsWhitespace(PRUnichar aChar);
|
||||
|
||||
static PRBool HandleEnumeration(const nsAString &aStrValue,
|
||||
const nsStringArray &aEnumerationList);
|
||||
|
|
|
@ -176,6 +176,12 @@
|
|||
validate("1", "nonPositiveInteger-test-1", false);
|
||||
validate("-3452", "nonPositiveInteger-test-1", false);
|
||||
|
||||
validate("-1", "nonNegativeInteger-test-1", false);
|
||||
validate("0", "nonNegativeInteger-test-1", true);
|
||||
validate("1", "nonNegativeInteger-test-1", true);
|
||||
validate("501", "nonNegativeInteger-test-1", false);
|
||||
validate("499", "nonNegativeInteger-test-1", true);
|
||||
|
||||
validate("-1", "negativeInteger-test-1", true);
|
||||
validate("-22", "negativeInteger-test-1", true);
|
||||
validate("0", "negativeInteger-test-1", false);
|
||||
|
@ -595,6 +601,43 @@
|
|||
validate("n:s", "qname-test-1", true);
|
||||
validate("test:123456789", "qname-test-1", false);
|
||||
|
||||
validate("test:foo", "name-test-1", true);
|
||||
validate(":fooasdad", "name-test-1", true);
|
||||
validate("n:s", "name-test-1", true);
|
||||
validate("-test", "name-test-1", false);
|
||||
validate("t", "name-test-1", false);
|
||||
|
||||
validate("foo", "ncname-test-1", true);
|
||||
validate("_fooasdad", "ncname-test-1", true);
|
||||
validate("1foo", "ncname-test-1", false);
|
||||
validate("test:foo", "ncname-test-1", false);
|
||||
validate("t", "ncname-test-1", false);
|
||||
|
||||
validate("t123", "id-test-1", true);
|
||||
validate("n:s", "id-test-1", false);
|
||||
validate("-test", "id-test-1", false);
|
||||
validate("t", "id-test-1", false);
|
||||
|
||||
validate("t123", "idref-test-1", true);
|
||||
validate("n:s", "idref-test-1", false);
|
||||
validate("-test", "idref-test-1", false);
|
||||
validate("t", "idref-test-1", false);
|
||||
|
||||
validate("t123", "idrefs-test-1", true);
|
||||
validate("ns _123", "idrefs-test-1", true);
|
||||
validate("test \tfoo", "idrefs-test-1", true);
|
||||
validate("test t123 u456 v789", "idrefs-test-1", false);
|
||||
|
||||
validate("t123", "nmtoken-test-1", true);
|
||||
validate("n:s-1", "nmtoken-test-1", true);
|
||||
validate("tes t", "nmtoken-test-1", false);
|
||||
validate("t", "nmtoken-test-1", false);
|
||||
|
||||
validate("t123", "nmtokens-test-1", true);
|
||||
validate("ns _123", "nmtokens-test-1", true);
|
||||
validate("test \tfoo", "nmtokens-test-1", true);
|
||||
validate("test t123 u456 v789", "nmtokens-test-1", false);
|
||||
|
||||
validate("true false 0 1", "list-test-1", true);
|
||||
validate("true false e 1", "list-test-1", false);
|
||||
|
||||
|
|
|
@ -29,6 +29,13 @@
|
|||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="nonNegativeInteger-test-1">
|
||||
<restriction base='nonNegativeInteger'>
|
||||
<totalDigits value="3" />
|
||||
<maxInclusive value="500" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="positiveInteger-test-1">
|
||||
<restriction base='positiveInteger'>
|
||||
<totalDigits value="3"/>
|
||||
|
@ -414,6 +421,55 @@
|
|||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="name-test-1">
|
||||
<restriction base='Name'>
|
||||
<maxLength value="13"/>
|
||||
<minLength value="3"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="ncname-test-1">
|
||||
<restriction base='NCName'>
|
||||
<maxLength value="13"/>
|
||||
<minLength value="3"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="id-test-1">
|
||||
<restriction base='ID'>
|
||||
<maxLength value="13"/>
|
||||
<minLength value="3"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="idref-test-1">
|
||||
<restriction base='IDREF'>
|
||||
<maxLength value="13"/>
|
||||
<minLength value="3"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="idrefs-test-1">
|
||||
<restriction base='IDREFS'>
|
||||
<maxLength value="13"/>
|
||||
<minLength value="3"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="nmtoken-test-1">
|
||||
<restriction base='NMTOKEN'>
|
||||
<maxLength value="13"/>
|
||||
<minLength value="3"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="nmtokens-test-1">
|
||||
<restriction base='NMTOKENS'>
|
||||
<maxLength value="13"/>
|
||||
<minLength value="3"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name='better-us-zipcode'>
|
||||
<restriction base='string'>
|
||||
<pattern value='[0-9]{5}(-[0-9]{4})?'/>
|
||||
|
|
Загрузка…
Ссылка в новой задаче