XForms bug 329136 - XForms needs to validate instance documents against their schema. r=aaronr, allan

This commit is contained in:
doronr%us.ibm.com 2006-04-05 16:51:11 +00:00
parent af73fbf542
commit ecc43aa481
5 changed files with 112 additions and 24 deletions

View File

@ -1518,6 +1518,62 @@ nsXFormsModelElement::ValidateNode(nsIDOMNode *aInstanceNode, PRBool *aResult)
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::ValidateDocument(nsIDOMDocument *aInstanceDocument,
PRBool *aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_ARG(aInstanceDocument);
/*
This will process the instance document and check for schema validity. It
will mark nodes in the document with their schema types using nsIProperty
until it hits a structural schema validation error. So if the instance
document's XML structure is invalid, don't expect type properties to be
set.
Note that if the structure is fine but some simple types nodes (nodes
that contain text only) are invalid (say one has a empty nodeValue but
should be a date), the schema validator will continue processing and add
the type properties. Schema validation will return false at the end.
*/
nsCOMPtr<nsIDOMElement> element;
nsresult rv = aInstanceDocument->GetDocumentElement(getter_AddRefs(element));
NS_ENSURE_SUCCESS(rv, rv);
PRBool isValid = PR_FALSE;
// get namespace from node
nsAutoString nsuri;
element->GetNamespaceURI(nsuri);
nsCOMPtr<nsISchemaCollection> schemaColl = do_QueryInterface(mSchemas);
NS_ENSURE_STATE(schemaColl);
nsCOMPtr<nsISchema> schema;
schemaColl->GetSchema(nsuri, getter_AddRefs(schema));
if (schema) {
nsXFormsSchemaValidator validator;
validator.LoadSchema(schema);
// Validate will validate the node and its subtree, as per the schema
// specification.
isValid = validator.Validate(element);
} else {
// no schema found for the instance document's namespace.
nsCOMPtr<nsIDOMNode> instanceElement;
nsXFormsUtils::GetInstanceNodeForData(element,
getter_AddRefs(instanceElement));
const PRUnichar *strings[] = { nsuri.get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("noSchemaForInstance"),
strings, 1, instanceElement, nsnull);
rv = NS_ERROR_UNEXPECTED;
}
*aResult = isValid;
return rv;
}
/*
* SUBMIT_SERIALIZE_NODE - node is to be serialized
* SUBMIT_SKIP_NODE - node is not to be serialized
@ -1588,6 +1644,21 @@ nsXFormsModelElement::GetTypeFromNode(nsIDOMNode *aInstanceData,
// If there was no type information on the node itself, check for a type
// bound to the node via \<xforms:bind\>
if (!typeVal && !mNodeToType.Get(aInstanceData, &typeVal)) {
// check if schema validation left us a nsISchemaType*
nsCOMPtr<nsIContent> content = do_QueryInterface(aInstanceData);
if (content) {
nsISchemaType *type;
nsCOMPtr<nsIAtom> myAtom = do_GetAtom("xsdtype");
type = NS_STATIC_CAST(nsISchemaType *, content->GetProperty(myAtom));
if (type) {
type->GetName(aType);
type->GetTargetNamespace(aNSUri);
return NS_OK;
}
}
// No type information found
return NS_ERROR_NOT_AVAILABLE;
}
@ -1932,6 +2003,37 @@ nsXFormsModelElement::MaybeNotifyCompletion()
nsXFormsUtils::DispatchEvent(model->mElement, eEvent_ModelConstructDone);
}
// validate the instance documents becauar we want schemaValidation to add
// schema type properties from the schema file unto our instance document
// elements. We don't care about the validation results.
if (mInstanceDocuments) {
PRUint32 instCount;
mInstanceDocuments->GetLength(&instCount);
if (instCount) {
nsCOMPtr<nsIDOMDocument> document;
for (PRUint32 i = 0; i < instCount; ++i) {
nsIInstanceElementPrivate* instEle = mInstanceDocuments->GetInstanceAt(i);
nsCOMPtr<nsIXFormsNSInstanceElement> NSInstEle(instEle);
NSInstEle->GetInstanceDocument(getter_AddRefs(document));
NS_ASSERTION(document, "nsIXFormsNSInstanceElement::GetInstanceDocument returned null?!");
if (document) {
PRBool isValid = PR_FALSE;
ValidateDocument(document, &isValid);
if (!isValid) {
nsCOMPtr<nsIDOMElement> instanceElement;
instEle->GetElement(getter_AddRefs(instanceElement));
nsXFormsUtils::ReportError(NS_LITERAL_STRING("instDocumentInvalid"),
instanceElement);
}
}
}
}
}
nsXFormsModelElement::ProcessDeferredBinds(domDoc);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);

View File

@ -349,7 +349,10 @@ private:
NS_HIDDEN_(nsresult) HandleUnload(nsIDOMEvent *aEvent);
NS_HIDDEN_(nsresult) RefreshSubTree(nsXFormsControlListItem *aCurrent,
PRBool aForceRebind);
PRBool aForceRebind);
NS_HIDDEN_(nsresult) ValidateDocument(nsIDOMDocument *aInstanceDocument,
PRBool *aResult);
nsIDOMElement *mElement;
nsCOMPtr<nsISchemaLoader> mSchemas;

View File

@ -83,28 +83,12 @@ nsXFormsSchemaValidator::ValidateString(const nsAString & aValue,
}
PRBool
nsXFormsSchemaValidator::ValidateNode(nsIDOMNode* aElement,
const nsAString & aType,
const nsAString & aNamespace)
nsXFormsSchemaValidator::Validate(nsIDOMNode* aElement)
{
PRBool isValid = PR_FALSE;
NS_ENSURE_TRUE(mSchemaValidator, isValid);
if (aNamespace.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
// XXX: currently, we will only support validating a lone node. When
// we get complex type support, we should load the schema for the xforms
// types and use ValidateAgainstType like below.
nsAutoString nodeValue;
nsCOMPtr<nsIDOM3Node> domNode3 = do_QueryInterface(aElement);
domNode3->GetTextContent(nodeValue);
isValid = ValidateString(nodeValue, aType, aNamespace);
} else {
nsCOMPtr<nsISchemaType> type;
if (GetType(aType, aNamespace, getter_AddRefs(type))) {
mSchemaValidator->ValidateAgainstType(aElement, type, &isValid);
}
}
mSchemaValidator->Validate(aElement, &isValid);
return isValid;
}

View File

@ -64,15 +64,12 @@ public:
const nsAString & aNamespace);
/**
* Validates a node against a namespace and schema type
* Validates a node and its subtree against the loaded schema(s)
*
* @param aElement Node to validate
* @param aType Type
* @param aNamespace Namespace
* @return Whether the string is valid or not
*/
PRBool ValidateNode(nsIDOMNode* aElement, const nsAString & aType,
const nsAString & aNamespace);
PRBool Validate(nsIDOMNode* aElement);
/**
* Returns a nsISchemaType given an type and namespace

View File

@ -71,10 +71,12 @@ externalLinkLoadOrigin = XForms Error (32): Security check failed! Trying to loa
instanceNotFound = XForms Error (33): Could not find instance with id == '%S'
defInstanceNotFound = XForms Error (34): Could not find default instance
MDGLoopError = XForms Error (35): There are loops in the bindings of the model!
noSchemaForInstance = XForms Error (36): Could not find a schema for validating the instance document (namespace=%S)
# Warning Messages:
warnSOAP = XForms Warning (1): You are using the SOAP post feature, which is an experimental feature! Beware that the functionality might change, and forms may stop working at any time.
warnMailtoBodyParam = XForms Warning (2): The submission action uri already contains a body parameter.
instDocumentInvalid = XForms Warning (3): Instance document did not validate.
# XForms Permission Messages:
xformsXDPermissionDialogTitle = Allowed Sites - XForms Cross Domain Access