Last Comment Bug 375983 - xsi:type not on root element is ignored
: xsi:type not on root element is ignored
Status: RESOLVED FIXED
: fixed1.8.0.12, fixed1.8.1.4
Product: Core
Classification: Components
Component: XForms (show other bugs)
: unspecified
: All All
: -- normal (vote)
: ---
Assigned To: Steve Speicher
: Stephen Pride
Mentors:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2007-03-30 06:29 PDT by Steve Speicher
Modified: 2007-04-23 16:30 PDT (History)
2 users (show)
See Also:
Crash Signature:
(edit)
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---


Attachments
test case (2.05 KB, application/xhtml+xml)
2007-03-30 06:30 PDT, Steve Speicher
no flags Details
patch (8.92 KB, patch)
2007-03-30 06:30 PDT, Steve Speicher
doronr: review+
aaronr: review+
Details | Diff | Review
patch for checkin (9.10 KB, patch)
2007-04-03 09:33 PDT, Steve Speicher
no flags Details | Diff | Review

Description Steve Speicher 2007-03-30 06:29:28 PDT
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
Build Identifier: 

When a referenced, or inline, xml instance has nodes with
redefined types using xsi:type, this information is ignored.
Validator only looks for it on ValidateNode(node) that is passed
in, which is typically the root document element only and then
walks the DOM with internal methods that track location along
associated schema.  Need to check for xsi:type on elements.
Note, this could be changed if and when DOM Level 3 Core's
Element.schemaTypeInfo

Reproducible: Always
Comment 1 Steve Speicher 2007-03-30 06:30:04 PDT
Created attachment 260119 [details]
test case
Comment 2 Steve Speicher 2007-03-30 06:30:38 PDT
Created attachment 260120 [details] [diff] [review]
patch
Comment 3 Doron Rosenberg (IBM) 2007-03-30 06:45:12 PDT
Comment on attachment 260120 [details] [diff] [review]
patch

>? xsitype.diff
>Index: nsSchemaValidator.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/schema-validation/src/nsSchemaValidator.cpp,v
>retrieving revision 1.36
>diff -u -8 -p -r1.36 nsSchemaValidator.cpp
>--- nsSchemaValidator.cpp	27 Mar 2007 21:55:06 -0000	1.36
>+++ nsSchemaValidator.cpp	30 Mar 2007 01:38:58 -0000
>@@ -170,87 +170,23 @@ nsSchemaValidator::Validate(nsIDOMNode* 
>   LOG(("--------- nsSchemaValidator::Validate called ---------"));
> 
>   if (!aElement)
>     return NS_ERROR_SCHEMAVALIDATOR_NO_DOM_NODE_SPECIFIED;
> 
>   // init the override
>   mForceInvalid = PR_FALSE;
> 
>-  nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(aElement);
>-  NS_ENSURE_STATE(domElement);
>-
>-  PRBool hasTypeAttribute = PR_FALSE;
>-  nsresult rv = domElement->HasAttributeNS(NS_LITERAL_STRING(
>-                                             NS_SCHEMA_INSTANCE_NAMESPACE),
>-                                           NS_LITERAL_STRING("type"),
>-                                           &hasTypeAttribute);
>-  NS_ENSURE_SUCCESS(rv, rv);
>-
>   // will hold the type to validate against
>   nsCOMPtr<nsISchemaType> type;
> 
>-  if (hasTypeAttribute) {
>-    LOG(("  -- found type attribute"));
>-
>-    nsAutoString typeAttribute;
>-    rv = domElement->GetAttributeNS(NS_LITERAL_STRING(
>-                                      NS_SCHEMA_INSTANCE_NAMESPACE),
>-                                    NS_LITERAL_STRING("type"),
>-                                    typeAttribute);
>-    NS_ENSURE_SUCCESS(rv, rv);
>-    LOG(("  Type is: %s", NS_ConvertUTF16toUTF8(typeAttribute).get()));
>-
>-    if (typeAttribute.IsEmpty())
>-      return NS_ERROR_SCHEMAVALIDATOR_NO_TYPE_FOUND;
>-
>-    // split type (ns:type) into namespace and type.
>-    nsCOMPtr<nsIParserService> parserService =
>-      do_GetService("@mozilla.org/parser/parser-service;1", &rv);
>-    NS_ENSURE_SUCCESS(rv, rv);
>-
>-    const nsAFlatString& qName = PromiseFlatString(typeAttribute);
>-    const PRUnichar *colon;
>-    rv = parserService->CheckQName(qName, PR_TRUE, &colon);
>-    NS_ENSURE_SUCCESS(rv, rv);
>-
>-    const PRUnichar* end;
>-    qName.EndReading(end);
>-
>-    nsAutoString schemaTypePrefix, schemaType, schemaTypeNamespace;
>-    if (!colon) {
>-      // colon not found, so no prefix
>-      schemaType.Assign(typeAttribute);
>-
>-      // get namespace from node
>-      aElement->GetNamespaceURI(schemaTypeNamespace);
>-    } else {
>-      schemaTypePrefix.Assign(Substring(qName.get(), colon));
>-      schemaType.Assign(Substring(colon + 1, end));
>-
>-      // get the namespace url from the prefix
>-      nsCOMPtr<nsIDOM3Node> domNode3 = do_QueryInterface(aElement);
>-      rv = domNode3->LookupNamespaceURI(schemaTypePrefix, schemaTypeNamespace);
>-      NS_ENSURE_SUCCESS(rv, rv);
>-    }
>-
>-    LOG(("  Type to validate against is %s:%s",
>-      NS_LossyConvertUTF16toASCII(schemaTypePrefix).get(),
>-      NS_LossyConvertUTF16toASCII(schemaType).get()));
>-
>-    // no schemas loaded and type is not builtin, abort
>-    if (!mSchema &&
>-        !schemaTypeNamespace.EqualsLiteral(NS_SCHEMA_1999_NAMESPACE) &&
>-        !schemaTypeNamespace.EqualsLiteral(NS_SCHEMA_2001_NAMESPACE))
>-      return NS_ERROR_SCHEMAVALIDATOR_NO_SCHEMA_LOADED;
>+  nsresult rv = GetElementXsiType(aElement, getter_AddRefs(type));
>+  NS_ENSURE_SUCCESS(rv, rv);
> 
>-    // get the type
>-    rv = GetType(schemaType, schemaTypeNamespace, getter_AddRefs(type));
>-    NS_ENSURE_SUCCESS(rv, rv);
>-  } else if (mSchema) {
>+  if (!type && mSchema) {
>     // no type attribute, look for an xsd:element in the schema that matches
>     LOG(("   -- no type attribute found, so looking for matching xsd:element"));
> 
>     // get namespace from node
>     nsAutoString schemaTypeNamespace;
>     rv = aElement->GetNamespaceURI(schemaTypeNamespace);
>     NS_ENSURE_SUCCESS(rv, rv);
> 
>@@ -4281,30 +4217,119 @@ nsSchemaValidator::ValidateComplexPartic
> 
>   leftOvers.swap(*aLeftOvers);
>   *aNotFound = notFound;
>   *aResult = isValid;
>   return rv;
> }
> 
> nsresult
>+nsSchemaValidator::GetElementXsiType(nsIDOMNode*     aNode,
>+                                  nsISchemaType** aType)
>+{
>+
>+  nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(aNode);
>+  NS_ENSURE_STATE(domElement);
>+
>+  PRBool hasTypeAttribute = PR_FALSE;
>+  nsresult rv = domElement->HasAttributeNS(NS_LITERAL_STRING(
>+                                             NS_SCHEMA_INSTANCE_NAMESPACE),
>+                                           NS_LITERAL_STRING("type"),
>+                                           &hasTypeAttribute);
>+  NS_ENSURE_SUCCESS(rv, rv);
>+
>+  /* XXX: This all may need to change when 
>+     element.GetSchemaTypeInfo() is implemented from DOM Level 3 Core,
>+     see:
>+     http://www.w3.org/TR/DOM-Level-3-Core/core.html#Attr-schemaTypeInfo
>+  */
>+
>+  if (hasTypeAttribute) {
>+    LOG(("  -- found xsi:type attribute"));
>+
>+    nsAutoString typeAttribute;
>+    rv = domElement->GetAttributeNS(NS_LITERAL_STRING(
>+                                      NS_SCHEMA_INSTANCE_NAMESPACE),
>+                                    NS_LITERAL_STRING("type"),
>+                                    typeAttribute);
>+    NS_ENSURE_SUCCESS(rv, rv);
>+    LOG(("  Type is: %s", NS_ConvertUTF16toUTF8(typeAttribute).get()));
>+
>+    if (typeAttribute.IsEmpty())
>+      return NS_ERROR_SCHEMAVALIDATOR_NO_TYPE_FOUND;
>+
>+    // split type (ns:type) into namespace and type.
>+    nsCOMPtr<nsIParserService> parserService =
>+      do_GetService("@mozilla.org/parser/parser-service;1", &rv);
>+    NS_ENSURE_SUCCESS(rv, rv);
>+
>+    const nsAFlatString& qName = PromiseFlatString(typeAttribute);
>+    const PRUnichar *colon;
>+    rv = parserService->CheckQName(qName, PR_TRUE, &colon);
>+    NS_ENSURE_SUCCESS(rv, rv);
>+
>+    const PRUnichar* end;
>+    qName.EndReading(end);
>+
>+    nsAutoString schemaTypePrefix, schemaType, schemaTypeNamespace;
>+    if (!colon) {
>+      // colon not found, so no prefix
>+      schemaType.Assign(typeAttribute);
>+
>+      // get namespace from node
>+      aNode->GetNamespaceURI(schemaTypeNamespace);
>+    } else {
>+      schemaTypePrefix.Assign(Substring(qName.get(), colon));
>+      schemaType.Assign(Substring(colon + 1, end));
>+
>+      // get the namespace url from the prefix
>+      nsCOMPtr<nsIDOM3Node> domNode3 = do_QueryInterface(aNode);
>+      rv = domNode3->LookupNamespaceURI(schemaTypePrefix, schemaTypeNamespace);
>+      NS_ENSURE_SUCCESS(rv, rv);
>+    }
>+
>+    LOG(("  Type to validate against is %s:%s",
>+      NS_LossyConvertUTF16toASCII(schemaTypePrefix).get(),
>+      NS_LossyConvertUTF16toASCII(schemaType).get()));
>+
>+    // no schemas loaded and type is not builtin, abort
>+    if (!mSchema &&
>+        !schemaTypeNamespace.EqualsLiteral(NS_SCHEMA_1999_NAMESPACE) &&
>+        !schemaTypeNamespace.EqualsLiteral(NS_SCHEMA_2001_NAMESPACE))
>+      return NS_ERROR_SCHEMAVALIDATOR_NO_SCHEMA_LOADED;
>+
>+    // get the type
>+    rv = GetType(schemaType, schemaTypeNamespace, aType);
>+    NS_ENSURE_SUCCESS(rv, rv);
>+  }
>+
>+  return rv;
>+}
>+
>+nsresult
> nsSchemaValidator::ValidateComplexElement(nsIDOMNode* aNode,
>                                           nsISchemaParticle *aSchemaParticle,
>                                           PRBool *aResult)
> {
>   PRBool isValid = PR_FALSE;
> 
>   nsCOMPtr<nsISchemaElement> schemaElement(do_QueryInterface(aSchemaParticle));
> 
>   if (!schemaElement)
>     return NS_ERROR_UNEXPECTED;
> 
>+  // will hold the type to validate against
>   nsCOMPtr<nsISchemaType> type;
>-  nsresult rv = schemaElement->GetType(getter_AddRefs(type));
>-  NS_ENSURE_SUCCESS(rv, rv);
>+
>+  nsresult rv = GetElementXsiType(aNode, getter_AddRefs(type));
>+
>+  if (!type) {
>+    rv = schemaElement->GetType(getter_AddRefs(type));
>+    NS_ENSURE_SUCCESS(rv, rv);
>+  }
> 
>   if (!type)
>     return NS_ERROR_UNEXPECTED;
> 
>   PRUint16 typeValue;
>   rv = type->GetSchemaType(&typeValue);
>   NS_ENSURE_SUCCESS(rv, rv);
> 
>Index: nsSchemaValidator.h
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/schema-validation/src/nsSchemaValidator.h,v
>retrieving revision 1.12
>diff -u -8 -p -r1.12 nsSchemaValidator.h
>--- nsSchemaValidator.h	13 Mar 2007 05:28:21 -0000	1.12
>+++ nsSchemaValidator.h	30 Mar 2007 01:38:59 -0000
>@@ -345,16 +345,17 @@ private:
>   nsresult ValidateSchemaAttribute(nsIDOMNode* aNode, nsISchemaAttribute *aAttr,
>                                    const nsAString & aAttrName,
>                                    PRUint32 *aFoundAttrCount, PRBool *aResult);
>   nsresult ValidateSchemaAttributeGroup(nsIDOMNode* aNode,
>                                         nsISchemaAttributeGroup *aAttr,
>                                         const nsAString & aAttrName,
>                                         PRUint32 *aFoundAttrCount,
>                                         PRBool *aResult);
>+  nsresult GetElementXsiType(nsIDOMNode* aNode, nsISchemaType** aType);
> 
> static void
> ReleaseObject(void    *aObject,
>               nsIAtom *aPropertyName,
>               void    *aPropertyValue,
>               void    *aData)
> {
>   NS_STATIC_CAST(nsISupports *, aPropertyValue)->Release();
Comment 4 aaronr 2007-04-02 16:55:46 PDT
Comment on attachment 260120 [details] [diff] [review]
patch

>Index: nsSchemaValidator.cpp
>===================================================================

> nsresult
>+nsSchemaValidator::GetElementXsiType(nsIDOMNode*     aNode,
>+                                  nsISchemaType** aType)
>+{
>+

nit: I know the style rules in schema-validator are more lax, but at least make the parameter types line up :-)


> nsSchemaValidator::ValidateComplexElement(nsIDOMNode* aNode,
>                                           nsISchemaParticle *aSchemaParticle,
>                                           PRBool *aResult)
> {
>   PRBool isValid = PR_FALSE;
> 
>   nsCOMPtr<nsISchemaElement> schemaElement(do_QueryInterface(aSchemaParticle));
> 
>   if (!schemaElement)
>     return NS_ERROR_UNEXPECTED;
> 
>+  // will hold the type to validate against
>   nsCOMPtr<nsISchemaType> type;
>-  nsresult rv = schemaElement->GetType(getter_AddRefs(type));
>-  NS_ENSURE_SUCCESS(rv, rv);
>+
>+  nsresult rv = GetElementXsiType(aNode, getter_AddRefs(type));
>+

nit: shouldn't you NS_ENSURE_SUCCESS(rv, rv) here?

>+  if (!type) {
>+    rv = schemaElement->GetType(getter_AddRefs(type));
>+    NS_ENSURE_SUCCESS(rv, rv);
>+  }
> 
>   if (!type)
>     return NS_ERROR_UNEXPECTED;

nit: shouldn't you move this up into the if (!type) test?  Otherwise you are running the same test twice if xsi:type is set, when you don't really need to.

with those, r=me
Comment 5 Steve Speicher 2007-04-03 09:33:30 PDT
Created attachment 260464 [details] [diff] [review]
patch for checkin
Comment 6 aaronr 2007-04-03 10:14:56 PDT
checked in for sspeiche
Comment 7 aaronr 2007-04-23 16:30:16 PDT
checked into 1.8 branch on 2007-04-12
checked into 1.8.0 branch on 2007-04-16

Note You need to log in before you can comment on or make changes to this bug.