2833 lines
89 KiB
C++
2833 lines
89 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is Mozilla.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications. Portions created by Netscape Communications are
|
|
* Copyright (C) 2001 by Netscape Communications. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Vidur Apparao <vidur@netscape.com> (original author)
|
|
*/
|
|
|
|
#include "nsSchemaPrivate.h"
|
|
#include "nsSchemaLoader.h"
|
|
|
|
// content includes
|
|
#include "nsIContent.h"
|
|
#include "nsINameSpaceManager.h"
|
|
#include "nsINodeInfo.h"
|
|
#include "nsIDOMDocument.h"
|
|
|
|
// loading includes
|
|
#include "nsIXMLHttpRequest.h"
|
|
#include "nsIDOMEvent.h"
|
|
#include "nsIDOMEventListener.h"
|
|
#include "nsIDOMEventTarget.h"
|
|
#include "nsNetUtil.h"
|
|
|
|
// string includes
|
|
#include "nsReadableUtils.h"
|
|
|
|
// XPConnect includes
|
|
#include "nsIXPConnect.h"
|
|
#include "nsIScriptSecurityManager.h"
|
|
#include "nsICodebasePrincipal.h"
|
|
|
|
// XPCOM includes
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIComponentManager.h"
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// nsSchemaAtoms implementation
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
|
|
// Statics
|
|
nsIAtom* nsSchemaAtoms::sAnyType_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sString_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sNormalizedString_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sToken_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sByte_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sUnsignedByte_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sBase64Binary_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sHexBinary_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sInteger_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sPositiveInteger_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sNegativeInteger_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sNonnegativeInteger_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sNonpositiveInteger_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sInt_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sUnsignedInt_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sLong_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sUnsignedLong_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sShort_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sUnsignedShort_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sDecimal_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sFloat_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sDouble_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sBoolean_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sTime_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sDateTime_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sDuration_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sDate_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sGMonth_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sGYear_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sGYearMonth_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sGDay_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sGMonthDay_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sName_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sQName_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sNCName_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sAnyUri_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sLanguage_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sID_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sIDREF_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sIDREFS_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sENTITY_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sENTITIES_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sNOTATION_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sNMTOKEN_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sNMTOKENS_atom = nsnull;
|
|
|
|
nsIAtom* nsSchemaAtoms::sElement_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sModelGroup_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sAny_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sAttribute_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sAttributeGroup_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sSimpleType_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sComplexType_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sSimpleContent_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sComplexContent_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sAll_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sChoice_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sSequence_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sAnyAttribute_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sRestriction_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sExtension_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sAnnotation_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sList_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sUnion_atom = nsnull;
|
|
|
|
nsIAtom* nsSchemaAtoms::sMinExclusive_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sMinInclusive_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sMaxExclusive_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sMaxInclusive_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sTotalDigits_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sFractionDigits_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sLength_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sMinLength_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sMaxLength_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sEnumeration_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sWhiteSpace_atom = nsnull;
|
|
nsIAtom* nsSchemaAtoms::sPattern_atom = nsnull;
|
|
|
|
void
|
|
nsSchemaAtoms::CreateSchemaAtoms()
|
|
{
|
|
sAnyType_atom = NS_NewAtom("anyType");
|
|
sString_atom = NS_NewAtom("string");
|
|
sNormalizedString_atom = NS_NewAtom("normalizedString");
|
|
sToken_atom = NS_NewAtom("token");
|
|
sByte_atom = NS_NewAtom("byte");
|
|
sUnsignedByte_atom = NS_NewAtom("unsignedByte");
|
|
sBase64Binary_atom = NS_NewAtom("base64Binary");
|
|
sHexBinary_atom = NS_NewAtom("hexBinary");
|
|
sInteger_atom = NS_NewAtom("integer");
|
|
sPositiveInteger_atom = NS_NewAtom("positiveInteger");
|
|
sNegativeInteger_atom = NS_NewAtom("negativeInteger");
|
|
sNonnegativeInteger_atom = NS_NewAtom("nonNegativeInteger");
|
|
sNonpositiveInteger_atom = NS_NewAtom("nonPositiveInteger");
|
|
sInt_atom = NS_NewAtom("int");
|
|
sUnsignedInt_atom = NS_NewAtom("unsignedInt");
|
|
sLong_atom = NS_NewAtom("long");
|
|
sUnsignedLong_atom = NS_NewAtom("unsignedLong");
|
|
sShort_atom = NS_NewAtom("short");
|
|
sUnsignedShort_atom = NS_NewAtom("unsignedShort");
|
|
sDecimal_atom = NS_NewAtom("decimal");
|
|
sFloat_atom = NS_NewAtom("float");
|
|
sDouble_atom = NS_NewAtom("double");
|
|
sBoolean_atom = NS_NewAtom("boolean");
|
|
sTime_atom = NS_NewAtom("time");
|
|
sDateTime_atom = NS_NewAtom("dateTime");
|
|
sDuration_atom = NS_NewAtom("duration");
|
|
sDate_atom = NS_NewAtom("date");
|
|
sGMonth_atom = NS_NewAtom("gMonth");
|
|
sGYear_atom = NS_NewAtom("gYear");
|
|
sGYearMonth_atom = NS_NewAtom("gYearMonth");
|
|
sGDay_atom = NS_NewAtom("gDay");
|
|
sGMonthDay_atom = NS_NewAtom("gMonthDay");
|
|
sName_atom = NS_NewAtom("name");
|
|
sQName_atom = NS_NewAtom("QName");
|
|
sNCName_atom = NS_NewAtom("NCName");
|
|
sAnyUri_atom = NS_NewAtom("anyUri");
|
|
sLanguage_atom = NS_NewAtom("language");
|
|
sID_atom = NS_NewAtom("ID");
|
|
sIDREF_atom = NS_NewAtom("IDREF");
|
|
sIDREFS_atom = NS_NewAtom("IDREFS");
|
|
sENTITY_atom = NS_NewAtom("ENTITY");
|
|
sENTITIES_atom = NS_NewAtom("ENTITIES");
|
|
sNOTATION_atom = NS_NewAtom("NOTATION");
|
|
sNMTOKEN_atom = NS_NewAtom("NMTOKEN");
|
|
sNMTOKENS_atom = NS_NewAtom("NMTOKENS");
|
|
|
|
sElement_atom = NS_NewAtom("element");
|
|
sModelGroup_atom = NS_NewAtom("group");
|
|
sAny_atom = NS_NewAtom("any");
|
|
sAttribute_atom = NS_NewAtom("attribute");
|
|
sAttributeGroup_atom = NS_NewAtom("attributeGroup");
|
|
sSimpleType_atom = NS_NewAtom("simpleType");
|
|
sComplexType_atom = NS_NewAtom("complexType");
|
|
sSimpleContent_atom = NS_NewAtom("simpleContent");
|
|
sComplexContent_atom = NS_NewAtom("complexContent");
|
|
sAll_atom = NS_NewAtom("all");
|
|
sChoice_atom = NS_NewAtom("choice");
|
|
sSequence_atom = NS_NewAtom("sequence");
|
|
sAnyAttribute_atom = NS_NewAtom("anyAttribute");
|
|
sRestriction_atom = NS_NewAtom("restriction");
|
|
sExtension_atom = NS_NewAtom("extension");
|
|
sAnnotation_atom = NS_NewAtom("annotation");
|
|
sList_atom = NS_NewAtom("list");
|
|
sUnion_atom = NS_NewAtom("union");
|
|
|
|
sMinExclusive_atom = NS_NewAtom("minExclusive");
|
|
sMinInclusive_atom = NS_NewAtom("minInclusive");
|
|
sMaxExclusive_atom = NS_NewAtom("maxExclusive");
|
|
sMaxInclusive_atom = NS_NewAtom("maxInclusive");
|
|
sTotalDigits_atom = NS_NewAtom("totalDigits");
|
|
sFractionDigits_atom = NS_NewAtom("fractionDigits");
|
|
sLength_atom = NS_NewAtom("length");
|
|
sMinLength_atom = NS_NewAtom("minLength");
|
|
sMaxLength_atom = NS_NewAtom("maxLength");
|
|
sEnumeration_atom = NS_NewAtom("enumeration");
|
|
sWhiteSpace_atom = NS_NewAtom("whiteSpace");
|
|
sPattern_atom = NS_NewAtom("pattern");
|
|
}
|
|
|
|
void
|
|
nsSchemaAtoms::DestroySchemaAtoms()
|
|
{
|
|
if (sAnyType_atom) {
|
|
NS_RELEASE(sAnyType_atom);
|
|
NS_RELEASE(sString_atom);
|
|
NS_RELEASE(sNormalizedString_atom);
|
|
NS_RELEASE(sToken_atom);
|
|
NS_RELEASE(sByte_atom);
|
|
NS_RELEASE(sUnsignedByte_atom);
|
|
NS_RELEASE(sBase64Binary_atom);
|
|
NS_RELEASE(sHexBinary_atom);
|
|
NS_RELEASE(sInteger_atom);
|
|
NS_RELEASE(sPositiveInteger_atom);
|
|
NS_RELEASE(sNegativeInteger_atom);
|
|
NS_RELEASE(sNonnegativeInteger_atom);
|
|
NS_RELEASE(sNonpositiveInteger_atom);
|
|
NS_RELEASE(sInt_atom);
|
|
NS_RELEASE(sUnsignedInt_atom);
|
|
NS_RELEASE(sLong_atom);
|
|
NS_RELEASE(sUnsignedLong_atom);
|
|
NS_RELEASE(sShort_atom);
|
|
NS_RELEASE(sUnsignedShort_atom);
|
|
NS_RELEASE(sDecimal_atom);
|
|
NS_RELEASE(sFloat_atom);
|
|
NS_RELEASE(sDouble_atom);
|
|
NS_RELEASE(sBoolean_atom);
|
|
NS_RELEASE(sTime_atom);
|
|
NS_RELEASE(sDateTime_atom);
|
|
NS_RELEASE(sDuration_atom);
|
|
NS_RELEASE(sDate_atom);
|
|
NS_RELEASE(sGMonth_atom);
|
|
NS_RELEASE(sGYear_atom);
|
|
NS_RELEASE(sGYearMonth_atom);
|
|
NS_RELEASE(sGDay_atom);
|
|
NS_RELEASE(sGMonthDay_atom);
|
|
NS_RELEASE(sName_atom);
|
|
NS_RELEASE(sQName_atom);
|
|
NS_RELEASE(sNCName_atom);
|
|
NS_RELEASE(sAnyUri_atom);
|
|
NS_RELEASE(sLanguage_atom);
|
|
NS_RELEASE(sID_atom);
|
|
NS_RELEASE(sIDREF_atom);
|
|
NS_RELEASE(sIDREFS_atom);
|
|
NS_RELEASE(sENTITY_atom);
|
|
NS_RELEASE(sENTITIES_atom);
|
|
NS_RELEASE(sNOTATION_atom);
|
|
NS_RELEASE(sNMTOKEN_atom);
|
|
NS_RELEASE(sNMTOKENS_atom);
|
|
|
|
NS_RELEASE(sElement_atom);
|
|
NS_RELEASE(sModelGroup_atom);
|
|
NS_RELEASE(sAny_atom);
|
|
NS_RELEASE(sAttribute_atom);
|
|
NS_RELEASE(sAttributeGroup_atom);
|
|
NS_RELEASE(sSimpleType_atom);
|
|
NS_RELEASE(sComplexType_atom);
|
|
NS_RELEASE(sSimpleContent_atom);
|
|
NS_RELEASE(sComplexContent_atom);
|
|
NS_RELEASE(sAll_atom);
|
|
NS_RELEASE(sChoice_atom);
|
|
NS_RELEASE(sSequence_atom);
|
|
NS_RELEASE(sAnyAttribute_atom);
|
|
NS_RELEASE(sRestriction_atom);
|
|
NS_RELEASE(sExtension_atom);
|
|
NS_RELEASE(sAnnotation_atom);
|
|
NS_RELEASE(sList_atom);
|
|
NS_RELEASE(sUnion_atom);
|
|
|
|
NS_RELEASE(sMinExclusive_atom);
|
|
NS_RELEASE(sMinInclusive_atom);
|
|
NS_RELEASE(sMaxExclusive_atom);
|
|
NS_RELEASE(sMaxInclusive_atom);
|
|
NS_RELEASE(sTotalDigits_atom);
|
|
NS_RELEASE(sFractionDigits_atom);
|
|
NS_RELEASE(sLength_atom);
|
|
NS_RELEASE(sMinLength_atom);
|
|
NS_RELEASE(sMaxLength_atom);
|
|
NS_RELEASE(sEnumeration_atom);
|
|
NS_RELEASE(sWhiteSpace_atom);
|
|
NS_RELEASE(sPattern_atom);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadListener implementation
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
|
|
class LoadListener : public nsIDOMEventListener {
|
|
public:
|
|
LoadListener(nsSchemaLoader* aLoader,
|
|
nsISchemaLoadListener* aListener,
|
|
nsIXMLHttpRequest* aRequest);
|
|
virtual ~LoadListener();
|
|
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIDOMEVENTLISTENER
|
|
|
|
private:
|
|
nsSchemaLoader* mLoader;
|
|
nsCOMPtr<nsISchemaLoadListener> mListener;
|
|
nsCOMPtr<nsIXMLHttpRequest> mRequest;
|
|
nsString mURI;
|
|
};
|
|
|
|
LoadListener::LoadListener(nsSchemaLoader* aLoader,
|
|
nsISchemaLoadListener* aListener,
|
|
nsIXMLHttpRequest* aRequest)
|
|
{
|
|
NS_INIT_ISUPPORTS();
|
|
mLoader = aLoader;
|
|
NS_ADDREF(mLoader);
|
|
mListener = aListener;
|
|
mRequest = aRequest;
|
|
}
|
|
|
|
LoadListener::~LoadListener()
|
|
{
|
|
NS_IF_RELEASE(mLoader);
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS1(LoadListener, nsIDOMEventListener)
|
|
|
|
/* void handleEvent (in nsIDOMEvent event); */
|
|
NS_IMETHODIMP
|
|
LoadListener::HandleEvent(nsIDOMEvent *event)
|
|
{
|
|
nsresult rv;
|
|
nsAutoString eventType;
|
|
|
|
event->GetType(eventType);
|
|
|
|
if (eventType.Equals(NS_LITERAL_STRING("load"))) {
|
|
nsCOMPtr<nsIDOMDocument> document;
|
|
nsCOMPtr<nsISchema> schema;
|
|
|
|
rv = mRequest->GetResponseXML(getter_AddRefs(document));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsCOMPtr<nsIDOMElement> element;
|
|
|
|
document->GetDocumentElement(getter_AddRefs(element));
|
|
if (element) {
|
|
rv = mLoader->ProcessSchemaElement(element, getter_AddRefs(schema));
|
|
}
|
|
else {
|
|
rv = NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
|
|
}
|
|
}
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mListener->OnLoad(schema);
|
|
}
|
|
else {
|
|
mListener->OnError(rv, NS_LITERAL_STRING("Failure processing schema document"));
|
|
}
|
|
}
|
|
else if (eventType.Equals(NS_LITERAL_STRING("error")) &&
|
|
mListener) {
|
|
mListener->OnError(NS_ERROR_SCHEMA_LOADING_ERROR,
|
|
NS_LITERAL_STRING("Failure loading"));
|
|
}
|
|
NS_IF_RELEASE(mLoader);
|
|
mListener = nsnull;
|
|
mRequest = nsnull;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// nsBuiltinSchemaCollection implementation
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
nsBuiltinSchemaCollection::nsBuiltinSchemaCollection()
|
|
{
|
|
NS_INIT_ISUPPORTS();
|
|
if (!nsSchemaAtoms::sAnyType_atom) {
|
|
nsSchemaAtoms::CreateSchemaAtoms();
|
|
}
|
|
}
|
|
|
|
nsBuiltinSchemaCollection::~nsBuiltinSchemaCollection()
|
|
{
|
|
mBuiltinTypesHash.Reset();
|
|
mSOAPTypeHash.Reset();
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS1(nsBuiltinSchemaCollection,
|
|
nsISchemaCollection)
|
|
|
|
/* nsISchema getSchema (in AString targetNamespace); */
|
|
NS_IMETHODIMP
|
|
nsBuiltinSchemaCollection::GetSchema(const nsAReadableString & targetNamespace,
|
|
nsISchema **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
return NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
|
|
}
|
|
|
|
/* nsISchemaElement getElement (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsBuiltinSchemaCollection::GetElement(const nsAReadableString & aName,
|
|
const nsAReadableString & aNamespace,
|
|
nsISchemaElement **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
/* nsISchemaAttribute getAttribute (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsBuiltinSchemaCollection::GetAttribute(const nsAReadableString & aName,
|
|
const nsAReadableString & aNamespace,
|
|
nsISchemaAttribute **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
static PRBool
|
|
IsSchemaNamespace(const nsAReadableString& aNamespace)
|
|
{
|
|
if (aNamespace.Equals(NS_LITERAL_STRING(NS_SCHEMA_2001_NAMESPACE)) ||
|
|
aNamespace.Equals(NS_LITERAL_STRING(NS_SCHEMA_1999_NAMESPACE))) {
|
|
return PR_TRUE;
|
|
}
|
|
else {
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
|
|
static PRBool
|
|
IsSOAPNamespace(const nsAReadableString& aNamespace)
|
|
{
|
|
if (aNamespace.Equals(NS_LITERAL_STRING(NS_SOAP_1_1_ENCODING_NAMESPACE)) ||
|
|
aNamespace.Equals(NS_LITERAL_STRING(NS_SOAP_1_2_ENCODING_NAMESPACE))) {
|
|
return PR_TRUE;
|
|
}
|
|
else {
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
|
|
/* nsISchemaType getType (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsBuiltinSchemaCollection::GetType(const nsAReadableString & aName,
|
|
const nsAReadableString & aNamespace,
|
|
nsISchemaType **_retval)
|
|
{
|
|
if (IsSchemaNamespace(aNamespace)) {
|
|
return GetBuiltinType(aName, aNamespace, _retval);
|
|
}
|
|
|
|
if (IsSOAPNamespace(aNamespace)) {
|
|
return GetSOAPType(aName, aNamespace, _retval);
|
|
}
|
|
|
|
return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
|
|
}
|
|
|
|
nsresult
|
|
nsBuiltinSchemaCollection::GetBuiltinType(const nsAReadableString& aName,
|
|
const nsAReadableString& aNamespace,
|
|
nsISchemaType** aType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsStringKey key(aName);
|
|
nsCOMPtr<nsISupports> sup = dont_AddRef(mBuiltinTypesHash.Get(&key));
|
|
if (sup) {
|
|
rv = CallQueryInterface(sup, aType);
|
|
}
|
|
else {
|
|
nsCOMPtr<nsIAtom> typeName = dont_AddRef(NS_NewAtom(aName));
|
|
PRUint16 typeVal;
|
|
if (typeName == nsSchemaAtoms::sAnyType_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ANYTYPE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sString_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_STRING;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNormalizedString_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sToken_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sByte_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_BYTE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sUnsignedByte_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sBase64Binary_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sHexBinary_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sInteger_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sPositiveInteger_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNegativeInteger_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNonnegativeInteger_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNonpositiveInteger_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sInt_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_INT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sUnsignedInt_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sLong_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_LONG;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sUnsignedLong_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sShort_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_SHORT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sUnsignedShort_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDecimal_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sFloat_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDouble_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sBoolean_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sTime_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_TIME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDateTime_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDuration_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DURATION;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDate_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DATE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGMonth_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGYear_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGYearMonth_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGDay_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GDAY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGMonthDay_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sName_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NAME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sQName_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_QNAME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNCName_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sAnyUri_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sLanguage_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sID_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ID;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sIDREF_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_IDREF;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sIDREFS_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sENTITY_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sENTITIES_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNOTATION_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNMTOKEN_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNMTOKENS_atom) {
|
|
typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS;
|
|
}
|
|
else {
|
|
NS_ERROR("Unknown builtin type");
|
|
return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
|
|
}
|
|
|
|
nsSchemaBuiltinType* builtin = new nsSchemaBuiltinType(typeVal);
|
|
if (!builtin) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
sup = builtin;
|
|
mBuiltinTypesHash.Put(&key, sup);
|
|
|
|
*aType = builtin;
|
|
NS_ADDREF(*aType);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsBuiltinSchemaCollection::GetSOAPType(const nsAReadableString& aName,
|
|
const nsAReadableString& aNamespace,
|
|
nsISchemaType** aType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsStringKey key(aName);
|
|
nsCOMPtr<nsISupports> sup = dont_AddRef(mSOAPTypeHash.Get(&key));
|
|
if (sup) {
|
|
rv = CallQueryInterface(sup, aType);
|
|
}
|
|
else {
|
|
if (aName.Equals(NS_LITERAL_STRING("Array"))) {
|
|
nsCOMPtr<nsISchemaType> anyType;
|
|
rv = GetBuiltinType(NS_LITERAL_STRING("anyType"),
|
|
NS_LITERAL_STRING(NS_SCHEMA_2001_NAMESPACE),
|
|
getter_AddRefs(anyType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsSOAPArray* array = new nsSOAPArray(anyType);
|
|
if (!array) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
sup = array;
|
|
mSOAPTypeHash.Put(&key, sup);
|
|
|
|
*aType = array;
|
|
NS_ADDREF(*aType);
|
|
}
|
|
else if (aName.Equals(NS_LITERAL_STRING("arrayType"))) {
|
|
nsSOAPArrayType* arrayType = new nsSOAPArrayType();
|
|
if (!arrayType) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
sup = arrayType;
|
|
mSOAPTypeHash.Put(&key, sup);
|
|
|
|
*aType = arrayType;
|
|
NS_ADDREF(*aType);
|
|
}
|
|
else {
|
|
rv = NS_ERROR_SCHEMA_UNKNOWN_TYPE;
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// nsSchemaLoader implementation
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
|
|
nsSchemaLoader::nsSchemaLoader()
|
|
{
|
|
NS_INIT_ISUPPORTS();
|
|
mBuiltinCollection = do_GetService(NS_BUILTINSCHEMACOLLECTION_CONTRACTID);
|
|
}
|
|
|
|
nsSchemaLoader::~nsSchemaLoader()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS2_CI(nsSchemaLoader,
|
|
nsISchemaLoader,
|
|
nsISchemaCollection)
|
|
|
|
|
|
/* nsISchema getSchema (in AString targetNamespace); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::GetSchema(const nsAReadableString & targetNamespace,
|
|
nsISchema **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
nsStringKey key(targetNamespace);
|
|
nsCOMPtr<nsISupports> sup = dont_AddRef(mSchemas.Get(&key));
|
|
nsCOMPtr<nsISchema> schema(do_QueryInterface(sup));
|
|
|
|
if (!schema) {
|
|
return NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE; // no schema for specified targetname
|
|
}
|
|
|
|
*_retval = schema;
|
|
NS_ADDREF(*_retval);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
/* nsISchemaElement getElement (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::GetElement(const nsAReadableString & aName,
|
|
const nsAReadableString & aNamespace,
|
|
nsISchemaElement **_retval)
|
|
{
|
|
nsCOMPtr<nsISchema> schema;
|
|
nsresult rv = GetSchema(aNamespace, getter_AddRefs(schema));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
return schema->GetElementByName(aName, _retval);
|
|
}
|
|
|
|
/* nsISchemaAttribute getAttribute (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::GetAttribute(const nsAReadableString & aName,
|
|
const nsAReadableString & aNamespace,
|
|
nsISchemaAttribute **_retval)
|
|
{
|
|
nsCOMPtr<nsISchema> schema;
|
|
nsresult rv = GetSchema(aNamespace, getter_AddRefs(schema));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
return schema->GetAttributeByName(aName, _retval);
|
|
}
|
|
|
|
/* nsISchemaType getType (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::GetType(const nsAReadableString & aName,
|
|
const nsAReadableString & aNamespace,
|
|
nsISchemaType **_retval)
|
|
{
|
|
if (IsSchemaNamespace(aNamespace) || IsSOAPNamespace(aNamespace)) {
|
|
return mBuiltinCollection->GetType(aName, aNamespace, _retval);
|
|
}
|
|
|
|
nsCOMPtr<nsISchema> schema;
|
|
nsresult rv = GetSchema(aNamespace, getter_AddRefs(schema));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
return schema->GetTypeByName(aName, _retval);
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::GetResolvedURI(const nsAReadableString& aSchemaURI,
|
|
const char* aMethod,
|
|
nsIURI** aURI)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIXPCNativeCallContext> cc;
|
|
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
|
|
if(NS_SUCCEEDED(rv)) {
|
|
rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
|
|
}
|
|
|
|
if (NS_SUCCEEDED(rv) && cc) {
|
|
JSContext* cx;
|
|
rv = cc->GetJSContext(&cx);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIScriptSecurityManager> secMan(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIURI> baseURI;
|
|
nsCOMPtr<nsIPrincipal> principal;
|
|
rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsCOMPtr<nsICodebasePrincipal> codebase = do_QueryInterface(principal);
|
|
if (codebase) {
|
|
codebase->GetURI(getter_AddRefs(baseURI));
|
|
}
|
|
}
|
|
|
|
rv = NS_NewURI(aURI, aSchemaURI, nsnull, baseURI);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = secMan->CheckLoadURIFromScript(cx, *aURI);
|
|
if (NS_FAILED(rv))
|
|
{
|
|
// Security check failed. The above call set a JS exception. The
|
|
// following lines ensure that the exception is propagated.
|
|
cc->SetExceptionWasThrown(PR_TRUE);
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
rv = NS_NewURI(aURI, aSchemaURI, nsnull);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
/* nsISchema load (in AString schemaURI); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::Load(const nsAReadableString& schemaURI,
|
|
nsISchema **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
nsCOMPtr<nsIURI> resolvedURI;
|
|
nsresult rv = GetResolvedURI(schemaURI, "load", getter_AddRefs(resolvedURI));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsCAutoString spec;
|
|
resolvedURI->GetSpec(spec);
|
|
|
|
nsCOMPtr<nsIXMLHttpRequest> request(do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv));
|
|
if (!request) {
|
|
return rv;
|
|
}
|
|
|
|
rv = request->OpenRequest("GET",
|
|
spec.get(),
|
|
PR_FALSE, nsnull, nsnull);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
// Force the mimetype of the returned stream to be xml.
|
|
rv = request->OverrideMimeType("text/xml");
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = request->Send(nsnull);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMDocument> document;
|
|
rv = request->GetResponseXML(getter_AddRefs(document));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMElement> element;
|
|
document->GetDocumentElement(getter_AddRefs(element));
|
|
if (element) {
|
|
rv = ProcessSchemaElement(element, _retval);
|
|
}
|
|
else {
|
|
rv = NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* void loadAsync (in AString schemaURI, in nsISchemaLoadListener listener); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::LoadAsync(const nsAReadableString& schemaURI,
|
|
nsISchemaLoadListener *aListener)
|
|
{
|
|
NS_ENSURE_ARG(aListener);
|
|
|
|
nsCOMPtr<nsIURI> resolvedURI;
|
|
nsresult rv = GetResolvedURI(schemaURI, "loadAsync", getter_AddRefs(resolvedURI));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
nsCAutoString spec;
|
|
resolvedURI->GetSpec(spec);
|
|
|
|
nsCOMPtr<nsIXMLHttpRequest> request(do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv));
|
|
if (!request) {
|
|
return rv;
|
|
}
|
|
|
|
rv = request->OpenRequest("GET",
|
|
spec.get(),
|
|
PR_TRUE, nsnull, nsnull);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
// Force the mimetype of the returned stream to be xml.
|
|
rv = request->OverrideMimeType("text/xml");
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMEventListener> listener;
|
|
LoadListener* listenerInst = new LoadListener(this, aListener, request);
|
|
if (!listenerInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
listener = listenerInst;
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(request));
|
|
if (!target) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
rv = target->AddEventListener(NS_LITERAL_STRING("load"),
|
|
listener, PR_FALSE);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = target->AddEventListener(NS_LITERAL_STRING("error"),
|
|
listener, PR_FALSE);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
// The listener keeps the request alive until its complete
|
|
rv = request->Send(nsnull);
|
|
|
|
return rv;
|
|
}
|
|
|
|
static const char* kSchemaNamespaces[] = {NS_SCHEMA_1999_NAMESPACE,
|
|
NS_SCHEMA_2001_NAMESPACE};
|
|
static PRUint32 kSchemaNamespacesLength = sizeof(kSchemaNamespaces) / sizeof(const char*);
|
|
|
|
/* nsISchema processSchemaElement (in nsIDOMElement element); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::ProcessSchemaElement(nsIDOMElement *element,
|
|
nsISchema **_retval)
|
|
{
|
|
NS_ENSURE_ARG(element);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
// Get target namespace and create the schema instance
|
|
nsAutoString targetNamespace, schemaNamespace;
|
|
element->GetAttribute(NS_LITERAL_STRING("targetNamespace"),
|
|
targetNamespace);
|
|
element->GetNamespaceURI(schemaNamespace);
|
|
nsSchema* schemaInst = new nsSchema(this, targetNamespace, schemaNamespace);
|
|
nsCOMPtr<nsISchema> schema = schemaInst;
|
|
if (!schema) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
nsChildElementIterator iterator(element,
|
|
kSchemaNamespaces, kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sElement_atom) {
|
|
nsCOMPtr<nsISchemaElement> schemaElement;
|
|
rv = ProcessElement(schemaInst, childElement,
|
|
getter_AddRefs(schemaElement));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddElement(schemaElement);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sComplexType_atom) {
|
|
nsCOMPtr<nsISchemaComplexType> complexType;
|
|
rv = ProcessComplexType(schemaInst, childElement,
|
|
getter_AddRefs(complexType));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddType(complexType);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sSimpleType_atom) {
|
|
nsCOMPtr<nsISchemaSimpleType> simpleType;
|
|
rv = ProcessSimpleType(schemaInst, childElement,
|
|
getter_AddRefs(simpleType));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddType(simpleType);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sAttribute_atom) {
|
|
nsCOMPtr<nsISchemaAttribute> attribute;
|
|
rv = ProcessAttribute(schemaInst, childElement,
|
|
getter_AddRefs(attribute));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddAttribute(attribute);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sAttributeGroup_atom) {
|
|
nsCOMPtr<nsISchemaAttributeGroup> attributeGroup;
|
|
rv = ProcessAttributeGroup(schemaInst, childElement,
|
|
getter_AddRefs(attributeGroup));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddAttributeGroup(attributeGroup);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sModelGroup_atom) {
|
|
nsCOMPtr<nsISchemaModelGroup> modelGroup;
|
|
rv = ProcessModelGroup(schemaInst, childElement,
|
|
tagName, nsnull, getter_AddRefs(modelGroup));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddModelGroup(modelGroup);
|
|
}
|
|
}
|
|
// For now, ignore the following
|
|
// annotations
|
|
// include
|
|
// import
|
|
// redefine
|
|
// notation
|
|
// identity-constraint elements
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
// Resolve all forward references
|
|
rv = schemaInst->Resolve();
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsStringKey key(targetNamespace);
|
|
mSchemas.Put(&key, schema);
|
|
|
|
*_retval = schema;
|
|
NS_ADDREF(*_retval);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
PRBool
|
|
ParseQualifiedName(nsIDOMElement* aContext,
|
|
const nsAReadableString& aQualifiedName,
|
|
nsAWritableString& aPrefix,
|
|
nsAWritableString& aLocalName,
|
|
nsAWritableString& aNamespaceURI)
|
|
{
|
|
nsReadingIterator<PRUnichar> pos, begin, end;
|
|
|
|
aQualifiedName.BeginReading(begin);
|
|
aQualifiedName.EndReading(end);
|
|
pos = begin;
|
|
|
|
if (FindCharInReadable(PRUnichar(':'), pos, end)) {
|
|
CopyUnicodeTo(begin, pos, aPrefix);
|
|
CopyUnicodeTo(++pos, end, aLocalName);
|
|
}
|
|
else {
|
|
CopyUnicodeTo(begin, end, aLocalName);
|
|
}
|
|
|
|
nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(aContext));
|
|
|
|
return node->LookupNamespaceURI(aPrefix, aNamespaceURI);
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::GetNewOrUsedType(nsSchema* aSchema,
|
|
nsIDOMElement* aContext,
|
|
const nsAReadableString& aTypeName,
|
|
nsISchemaType** aType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsAutoString prefix, localName, namespaceURI;
|
|
|
|
// See if there's a prefix and get the
|
|
// namespace associated with the prefix
|
|
rv = ParseQualifiedName(aContext, aTypeName, prefix,
|
|
localName, namespaceURI);
|
|
if ((prefix.Length() > 0) && NS_FAILED(rv)) {
|
|
// Unknown prefix
|
|
return NS_ERROR_SCHEMA_UNKNOWN_PREFIX;
|
|
}
|
|
|
|
*aType = nsnull;
|
|
nsAutoString targetNamespace;
|
|
aSchema->GetTargetNamespace(targetNamespace);
|
|
if (namespaceURI.IsEmpty() || namespaceURI.Equals(targetNamespace)) {
|
|
// It's a local type
|
|
rv = aSchema->GetTypeByName(localName, aType);
|
|
}
|
|
else {
|
|
rv = GetType(localName, namespaceURI, aType);
|
|
if (!*aType) {
|
|
return NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
|
|
}
|
|
}
|
|
|
|
// If we didn't get a type, we need to create a placeholder
|
|
if (NS_SUCCEEDED(rv) && !*aType) {
|
|
nsSchemaTypePlaceholder* placeholder = new nsSchemaTypePlaceholder(aSchema,
|
|
localName);
|
|
if (!placeholder) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
*aType = placeholder;
|
|
NS_ADDREF(*aType);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessElement(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISchemaElement** aSchemaElement)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsISchemaElement> schemaElement;
|
|
PRUint32 minOccurs, maxOccurs;
|
|
GetMinAndMax(aElement, &minOccurs, &maxOccurs);
|
|
|
|
// See if it's a reference or an actual element declaration
|
|
nsAutoString ref;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
|
|
if (ref.Length() > 0) {
|
|
nsSchemaElementRef* elementRef;
|
|
|
|
elementRef = new nsSchemaElementRef(aSchema, ref);
|
|
if (!elementRef) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
schemaElement = elementRef;
|
|
|
|
elementRef->SetMinOccurs(minOccurs);
|
|
elementRef->SetMaxOccurs(maxOccurs);
|
|
}
|
|
else {
|
|
nsAutoString name;
|
|
nsSchemaElement* elementInst;
|
|
|
|
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
|
|
elementInst = new nsSchemaElement(aSchema, name);
|
|
if (!elementInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
schemaElement = elementInst;
|
|
|
|
elementInst->SetMinOccurs(minOccurs);
|
|
elementInst->SetMaxOccurs(maxOccurs);
|
|
|
|
nsAutoString defaultValue, fixedValue;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("default"), defaultValue);
|
|
aElement->GetAttribute(NS_LITERAL_STRING("fixed"), fixedValue);
|
|
elementInst->SetConstraints(defaultValue, fixedValue);
|
|
|
|
nsAutoString nillable, abstract;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("nillable"), nillable);
|
|
aElement->GetAttribute(NS_LITERAL_STRING("abstract"), abstract);
|
|
elementInst->SetFlags(nillable.Equals(NS_LITERAL_STRING("true")),
|
|
abstract.Equals(NS_LITERAL_STRING("true")));
|
|
|
|
nsCOMPtr<nsISchemaType> schemaType;
|
|
nsAutoString typeStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("type"), typeStr);
|
|
if (typeStr.Length() > 0) {
|
|
rv = GetNewOrUsedType(aSchema, aElement, typeStr,
|
|
getter_AddRefs(schemaType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
// Look for the type as a child of the element
|
|
else {
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sSimpleType_atom) {
|
|
nsCOMPtr<nsISchemaSimpleType> simpleType;
|
|
|
|
rv = ProcessSimpleType(aSchema, childElement,
|
|
getter_AddRefs(simpleType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
schemaType = simpleType;
|
|
break;
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sComplexType_atom) {
|
|
nsCOMPtr<nsISchemaComplexType> complexType;
|
|
|
|
rv = ProcessComplexType(aSchema, childElement,
|
|
getter_AddRefs(complexType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
schemaType = complexType;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!schemaType) {
|
|
nsAutoString ns;
|
|
aElement->GetNamespaceURI(ns);
|
|
rv = GetType(NS_LITERAL_STRING("anyType"),
|
|
ns,
|
|
getter_AddRefs(schemaType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
rv = elementInst->SetType(schemaType);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
*aSchemaElement = schemaElement;
|
|
NS_ADDREF(*aSchemaElement);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessComplexType(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISchemaComplexType** aComplexType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsISchemaComplexType> complexType;
|
|
|
|
nsAutoString abstract, name;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("abstract"), abstract);
|
|
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
|
|
|
|
nsSchemaComplexType* typeInst;
|
|
typeInst = new nsSchemaComplexType(aSchema, name,
|
|
abstract.Equals(NS_LITERAL_STRING("true")));
|
|
if (!typeInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
complexType = typeInst;
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
PRUint16 contentModel = nsISchemaComplexType::CONTENT_MODEL_EMPTY;
|
|
PRUint16 derivation = nsISchemaComplexType::DERIVATION_SELF_CONTAINED;
|
|
nsCOMPtr<nsISchemaType> baseType;
|
|
nsCOMPtr<nsISchemaModelGroup> modelGroup;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sSimpleContent_atom) {
|
|
contentModel = nsISchemaComplexType::CONTENT_MODEL_SIMPLE;
|
|
|
|
rv = ProcessSimpleContent(aSchema,
|
|
childElement, typeInst,
|
|
&derivation, getter_AddRefs(baseType));
|
|
break;
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sComplexContent_atom) {
|
|
rv = ProcessComplexContent(aSchema,
|
|
childElement, typeInst,
|
|
&contentModel, &derivation,
|
|
getter_AddRefs(baseType));
|
|
break;
|
|
}
|
|
else if (tagName != nsSchemaAtoms::sAnnotation_atom) {
|
|
rv = ProcessComplexTypeBody(aSchema,
|
|
aElement, typeInst, nsnull,
|
|
&contentModel);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsAutoString mixed;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("mixed"), mixed);
|
|
if (mixed.Equals(NS_LITERAL_STRING("true"))) {
|
|
contentModel = nsISchemaComplexType::CONTENT_MODEL_MIXED;
|
|
}
|
|
|
|
typeInst->SetContentModel(contentModel);
|
|
typeInst->SetDerivation(derivation, baseType);
|
|
|
|
*aComplexType = complexType;
|
|
NS_ADDREF(*aComplexType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsSchemaLoader::ConstructArrayName(nsISchemaType* aType,
|
|
nsAWritableString& aName)
|
|
{
|
|
nsAutoString typeName;
|
|
|
|
aType->GetName(typeName);
|
|
aName.Assign(NS_LITERAL_STRING("ArrayOf") + typeName);
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ParseDimensions(nsSchema* aSchema,
|
|
nsIDOMElement* aAttrElement,
|
|
const nsAReadableString& aStr,
|
|
nsISchemaType* aBaseType,
|
|
nsISchemaType** aArrayType,
|
|
PRUint32* aDimension)
|
|
{
|
|
nsReadingIterator<PRUnichar> iter, done_reading;
|
|
aStr.BeginReading(iter);
|
|
aStr.EndReading(done_reading);
|
|
|
|
PRUint32 dimension = 1;
|
|
PRUnichar uc = *iter++;
|
|
if (uc != PRUnichar('[')) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
while (iter != done_reading) {
|
|
uc = *iter++;
|
|
if (uc == PRUnichar(',')) {
|
|
dimension++;
|
|
}
|
|
else if (uc == PRUnichar(']')) {
|
|
break;
|
|
}
|
|
}
|
|
*aDimension = dimension;
|
|
|
|
while ((iter != done_reading) && (*iter == PRUnichar(' '))) {
|
|
++iter;
|
|
}
|
|
|
|
// If there's still more to go, then create an array type
|
|
// based on the base and continue to parse
|
|
if ((iter != done_reading) && (*iter == PRUnichar('['))) {
|
|
nsAutoString name;
|
|
nsCOMPtr<nsISchemaType> myArrayType;
|
|
PRUint32 myDimension;
|
|
|
|
nsresult rv = ParseDimensions(aSchema, aAttrElement,
|
|
nsDependentSubstring(iter, done_reading),
|
|
aBaseType, getter_AddRefs(myArrayType),
|
|
&myDimension);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
ConstructArrayName(myArrayType, name);
|
|
nsSchemaComplexType* typeInst = new nsSchemaComplexType(aSchema,
|
|
name,
|
|
PR_FALSE);
|
|
if (!typeInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
nsCOMPtr<nsISchemaComplexType> complexType = typeInst;
|
|
|
|
nsCOMPtr<nsISchemaType> soapArray;
|
|
rv = GetType(NS_LITERAL_STRING("Array"),
|
|
NS_LITERAL_STRING(NS_SOAP_1_2_ENCODING_NAMESPACE),
|
|
getter_AddRefs(soapArray));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
typeInst->SetContentModel(nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY);
|
|
typeInst->SetDerivation(nsISchemaComplexType::DERIVATION_RESTRICTION_COMPLEX,
|
|
soapArray);
|
|
typeInst->SetArrayInfo(myArrayType, myDimension);
|
|
|
|
*aArrayType = typeInst;
|
|
}
|
|
else {
|
|
*aArrayType = aBaseType;
|
|
}
|
|
NS_ADDREF(*aArrayType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ParseArrayType(nsSchema* aSchema,
|
|
nsIDOMElement* aAttrElement,
|
|
const nsAReadableString& aStr,
|
|
nsISchemaType** aType,
|
|
PRUint32* aDimension)
|
|
{
|
|
PRInt32 offset;
|
|
|
|
offset = aStr.FindChar(PRUnichar('['));
|
|
if (offset == -1) {
|
|
return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
|
|
}
|
|
nsDependentSubstring typeStr(aStr, 0, offset);
|
|
|
|
nsCOMPtr<nsISchemaType> type;
|
|
nsresult rv = GetNewOrUsedType(aSchema, aAttrElement, typeStr,
|
|
getter_AddRefs(type));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsDependentSubstring dimensionStr(aStr, offset,
|
|
aStr.Length() - offset);
|
|
return ParseDimensions(aSchema, aAttrElement, dimensionStr, type,
|
|
aType, aDimension);
|
|
}
|
|
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessComplexTypeBody(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsSchemaComplexType* aComplexType,
|
|
nsSchemaModelGroup* aSequence,
|
|
PRUint16* aContentModel)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
*aContentModel = nsISchemaComplexType::CONTENT_MODEL_EMPTY;
|
|
|
|
nsCOMPtr<nsISchemaModelGroup> modelGroup;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if ((tagName == nsSchemaAtoms::sModelGroup_atom) ||
|
|
(tagName == nsSchemaAtoms::sAll_atom) ||
|
|
(tagName == nsSchemaAtoms::sChoice_atom) ||
|
|
(tagName == nsSchemaAtoms::sSequence_atom)) {
|
|
// We shouldn't already have a model group
|
|
if (modelGroup) {
|
|
return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
|
|
}
|
|
|
|
rv = ProcessModelGroup(aSchema,
|
|
childElement, tagName,
|
|
aSequence, getter_AddRefs(modelGroup));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
PRUint32 particleCount;
|
|
modelGroup->GetParticleCount(&particleCount);
|
|
if (particleCount) {
|
|
*aContentModel = nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY;
|
|
}
|
|
else {
|
|
PRUint16 compositor;
|
|
modelGroup->GetCompositor(&compositor);
|
|
|
|
PRUint32 minOccurs;
|
|
modelGroup->GetMinOccurs(&minOccurs);
|
|
|
|
if ((compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) &&
|
|
(minOccurs > 0)) {
|
|
*aContentModel = nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY;
|
|
}
|
|
}
|
|
|
|
if (aSequence) {
|
|
// Check if we were collapsed
|
|
if (modelGroup.get() != NS_STATIC_CAST(nsISchemaModelGroup*,
|
|
aSequence)) {
|
|
rv = aSequence->AddParticle(modelGroup);
|
|
}
|
|
}
|
|
else {
|
|
rv = aComplexType->SetModelGroup(modelGroup);
|
|
}
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
else if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
|
|
(tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
|
|
(tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
|
|
nsCOMPtr<nsISchemaAttributeComponent> attribute;
|
|
|
|
rv = ProcessAttributeComponent(aSchema,
|
|
childElement, tagName,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->AddAttribute(attribute);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
// XXX WSDL ugliness making itself into schemas. Hopefully this
|
|
// mechanism for specifying an array type in schemas will die
|
|
// when the Schema WG address qualified names in attribute
|
|
// default values.
|
|
if (tagName == nsSchemaAtoms::sAttribute_atom) {
|
|
#define NS_WSDL_NAMESPACE "http://schemas.xmlsoap.org/wsdl/"
|
|
nsAutoString arrayType;
|
|
childElement->GetAttributeNS(NS_LITERAL_STRING(NS_WSDL_NAMESPACE),
|
|
NS_LITERAL_STRING("arrayType"),
|
|
arrayType);
|
|
if (!arrayType.IsEmpty()) {
|
|
nsCOMPtr<nsISchemaType> arraySchemaType;
|
|
PRUint32 arrayDimension;
|
|
rv = ParseArrayType(aSchema,
|
|
childElement,
|
|
arrayType,
|
|
getter_AddRefs(arraySchemaType),
|
|
&arrayDimension);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->SetArrayInfo(arraySchemaType, arrayDimension);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleContent(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsSchemaComplexType* aComplexType,
|
|
PRUint16* aDerivation,
|
|
nsISchemaType** aBaseType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsISchemaType> baseType;
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
// A simpleContent element must have children
|
|
if (!iterator.HasChildNodes()) {
|
|
return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
|
|
}
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
nsAutoString baseStr;
|
|
if ((tagName == nsSchemaAtoms::sRestriction_atom) ||
|
|
(tagName == nsSchemaAtoms::sExtension_atom)) {
|
|
childElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
|
|
if (baseStr.Length() == 0) {
|
|
return NS_ERROR_SCHEMA_MISSING_TYPE;
|
|
}
|
|
|
|
rv = GetNewOrUsedType(aSchema, childElement, baseStr,
|
|
getter_AddRefs(baseType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsISchemaSimpleType> simpleBaseType;
|
|
if (tagName == nsSchemaAtoms::sRestriction_atom) {
|
|
*aDerivation = nsISchemaComplexType::DERIVATION_RESTRICTION_SIMPLE;
|
|
rv = ProcessSimpleContentRestriction(aSchema, childElement,
|
|
aComplexType, baseType,
|
|
getter_AddRefs(simpleBaseType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
*aDerivation = nsISchemaComplexType::DERIVATION_EXTENSION_SIMPLE;
|
|
|
|
nsCOMPtr<nsISchemaComplexType> complexBaseType(do_QueryInterface(baseType));
|
|
if (complexBaseType) {
|
|
// Copy over the attributes from the base type
|
|
// XXX Should really be cloning
|
|
PRUint32 attrIndex, attrCount;
|
|
complexBaseType->GetAttributeCount(&attrCount);
|
|
|
|
for (attrIndex = 0; attrIndex < attrCount; attrIndex++) {
|
|
nsCOMPtr<nsISchemaAttributeComponent> attribute;
|
|
|
|
rv = complexBaseType->GetAttributeByIndex(attrIndex,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->AddAttribute(attribute);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
rv = ProcessSimpleContentExtension(aSchema, childElement,
|
|
aComplexType, baseType,
|
|
getter_AddRefs(simpleBaseType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
if (simpleBaseType) {
|
|
rv = aComplexType->SetSimpleBaseType(simpleBaseType);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
*aBaseType = baseType;
|
|
NS_IF_ADDREF(*aBaseType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleContentRestriction(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsSchemaComplexType* aComplexType,
|
|
nsISchemaType* aBaseType,
|
|
nsISchemaSimpleType** aSimpleBaseType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
nsSchemaRestrictionType* restrictionInst;
|
|
nsCOMPtr<nsISchemaSimpleType> simpleBase;
|
|
|
|
restrictionInst = new nsSchemaRestrictionType(aSchema,
|
|
NS_LITERAL_STRING(""));
|
|
if (!restrictionInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
simpleBase = restrictionInst;
|
|
|
|
// The base type must actually be a complex type (which itself must
|
|
// have a simple base type.
|
|
nsCOMPtr<nsISchemaComplexType> complexBase = do_QueryInterface(aBaseType);
|
|
if (!complexBase) {
|
|
return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
|
|
}
|
|
|
|
nsCOMPtr<nsISchemaSimpleType> parentSimpleBase;
|
|
complexBase->GetSimpleBaseType(getter_AddRefs(parentSimpleBase));
|
|
|
|
if (parentSimpleBase) {
|
|
rv = restrictionInst->SetBaseType(parentSimpleBase);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sSimpleType_atom) {
|
|
nsCOMPtr<nsISchemaSimpleType> simpleType;
|
|
|
|
rv = ProcessSimpleType(aSchema, childElement,
|
|
getter_AddRefs(simpleType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = restrictionInst->SetBaseType(simpleType);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
else if ((tagName == nsSchemaAtoms::sMinExclusive_atom) ||
|
|
(tagName == nsSchemaAtoms::sMinInclusive_atom) ||
|
|
(tagName == nsSchemaAtoms::sMaxExclusive_atom) ||
|
|
(tagName == nsSchemaAtoms::sMaxInclusive_atom) ||
|
|
(tagName == nsSchemaAtoms::sTotalDigits_atom) ||
|
|
(tagName == nsSchemaAtoms::sFractionDigits_atom) ||
|
|
(tagName == nsSchemaAtoms::sLength_atom) ||
|
|
(tagName == nsSchemaAtoms::sMinLength_atom) ||
|
|
(tagName == nsSchemaAtoms::sMaxLength_atom) ||
|
|
(tagName == nsSchemaAtoms::sEnumeration_atom) ||
|
|
(tagName == nsSchemaAtoms::sWhiteSpace_atom) ||
|
|
(tagName == nsSchemaAtoms::sPattern_atom)) {
|
|
nsCOMPtr<nsISchemaFacet> facet;
|
|
|
|
rv = ProcessFacet(aSchema, childElement,
|
|
tagName, getter_AddRefs(facet));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = restrictionInst->AddFacet(facet);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
else if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
|
|
(tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
|
|
(tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
|
|
nsCOMPtr<nsISchemaAttributeComponent> attribute;
|
|
|
|
rv = ProcessAttributeComponent(aSchema,
|
|
childElement, tagName,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->AddAttribute(attribute);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
*aSimpleBaseType = simpleBase;
|
|
NS_IF_ADDREF(*aSimpleBaseType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleContentExtension(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsSchemaComplexType* aComplexType,
|
|
nsISchemaType* aBaseType,
|
|
nsISchemaSimpleType** aSimpleBaseType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
// If the base type is a complex type, it must itself have a simple
|
|
// base type
|
|
nsCOMPtr<nsISchemaComplexType> complexBase = do_QueryInterface(aBaseType);
|
|
if (complexBase) {
|
|
complexBase->GetSimpleBaseType(aSimpleBaseType);
|
|
}
|
|
else {
|
|
aBaseType->QueryInterface(NS_GET_IID(nsISchemaSimpleType),
|
|
(void**)aSimpleBaseType);
|
|
}
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
|
|
(tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
|
|
(tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
|
|
nsCOMPtr<nsISchemaAttributeComponent> attribute;
|
|
|
|
rv = ProcessAttributeComponent(aSchema,
|
|
childElement, tagName,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->AddAttribute(attribute);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessComplexContent(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsSchemaComplexType* aComplexType,
|
|
PRUint16* aContentModel,
|
|
PRUint16* aDerivation,
|
|
nsISchemaType** aBaseType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsISchemaType> baseType;
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
// A complexContent element must have children
|
|
if (!iterator.HasChildNodes()) {
|
|
return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
|
|
}
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
nsAutoString baseStr;
|
|
if ((tagName == nsSchemaAtoms::sRestriction_atom) ||
|
|
(tagName == nsSchemaAtoms::sExtension_atom)) {
|
|
childElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
|
|
if (baseStr.Length() == 0) {
|
|
return NS_ERROR_SCHEMA_MISSING_TYPE;
|
|
}
|
|
|
|
rv = GetNewOrUsedType(aSchema, childElement, baseStr,
|
|
getter_AddRefs(baseType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
if (tagName == nsSchemaAtoms::sRestriction_atom) {
|
|
*aDerivation = nsISchemaComplexType::DERIVATION_RESTRICTION_COMPLEX;
|
|
rv = ProcessComplexTypeBody(aSchema, childElement,
|
|
aComplexType, nsnull, aContentModel);
|
|
}
|
|
else {
|
|
*aDerivation = nsISchemaComplexType::DERIVATION_EXTENSION_COMPLEX;
|
|
|
|
nsCOMPtr<nsISchemaModelGroup> sequence;
|
|
nsSchemaModelGroup* sequenceInst = nsnull;
|
|
nsCOMPtr<nsISchemaComplexType> complexBaseType(do_QueryInterface(baseType));
|
|
if (complexBaseType) {
|
|
// XXX Should really be cloning
|
|
nsCOMPtr<nsISchemaModelGroup> baseGroup;
|
|
rv = complexBaseType->GetModelGroup(getter_AddRefs(baseGroup));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
if (baseGroup) {
|
|
// Create a new model group that's going to be the a sequence
|
|
// of the base model group and the content below
|
|
sequenceInst = new nsSchemaModelGroup(aSchema,
|
|
NS_LITERAL_STRING(""));
|
|
if (!sequenceInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
sequence = sequenceInst;
|
|
|
|
PRUint16 compositor;
|
|
baseGroup->GetCompositor(&compositor);
|
|
|
|
PRUint32 minOccurs, maxOccurs;
|
|
baseGroup->GetMinOccurs(&minOccurs);
|
|
baseGroup->GetMaxOccurs(&maxOccurs);
|
|
|
|
// If the base group also a sequence, we can collapse the
|
|
// two sequences.
|
|
if ((compositor == nsISchemaModelGroup::COMPOSITOR_SEQUENCE) &&
|
|
(minOccurs == 1) && (maxOccurs == 1)) {
|
|
PRUint32 pIndex, pCount;
|
|
baseGroup->GetParticleCount(&pCount);
|
|
for (pIndex = 0; pIndex < pCount; pIndex++) {
|
|
nsCOMPtr<nsISchemaParticle> particle;
|
|
|
|
rv = baseGroup->GetParticle(pIndex, getter_AddRefs(particle));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = sequenceInst->AddParticle(particle);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
sequenceInst->AddParticle(baseGroup);
|
|
}
|
|
|
|
aComplexType->SetModelGroup(sequence);
|
|
}
|
|
|
|
|
|
// Copy over the attributes from the base type
|
|
// XXX Should really be cloning
|
|
PRUint32 attrIndex, attrCount;
|
|
complexBaseType->GetAttributeCount(&attrCount);
|
|
|
|
for (attrIndex = 0; attrIndex < attrCount; attrIndex++) {
|
|
nsCOMPtr<nsISchemaAttributeComponent> attribute;
|
|
|
|
rv = complexBaseType->GetAttributeByIndex(attrIndex,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->AddAttribute(attribute);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
PRUint16 explicitContent;
|
|
rv = ProcessComplexTypeBody(aSchema, childElement,
|
|
aComplexType, sequenceInst,
|
|
&explicitContent);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
// If the explicit content is empty, get the content type
|
|
// from the base
|
|
if ((explicitContent == nsISchemaComplexType::CONTENT_MODEL_EMPTY) &&
|
|
complexBaseType) {
|
|
complexBaseType->GetContentModel(aContentModel);
|
|
}
|
|
else {
|
|
*aContentModel = explicitContent;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
nsAutoString mixed;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("mixed"), mixed);
|
|
if (mixed.Equals(NS_LITERAL_STRING("true"))) {
|
|
*aContentModel = nsISchemaComplexType::CONTENT_MODEL_MIXED;
|
|
}
|
|
|
|
*aBaseType = baseType;
|
|
NS_IF_ADDREF(*aBaseType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleType(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISchemaSimpleType** aSimpleType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsAutoString name;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sRestriction_atom) {
|
|
rv = ProcessSimpleTypeRestriction(aSchema, childElement,
|
|
name, aSimpleType);
|
|
break;
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sList_atom) {
|
|
rv = ProcessSimpleTypeList(aSchema, childElement,
|
|
name, aSimpleType);
|
|
break;
|
|
}
|
|
else if (tagName = nsSchemaAtoms::sUnion_atom) {
|
|
rv = ProcessSimpleTypeUnion(aSchema, childElement,
|
|
name, aSimpleType);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleTypeRestriction(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
const nsAReadableString& aName,
|
|
nsISchemaSimpleType** aSimpleType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsSchemaRestrictionType* restrictionInst;
|
|
nsCOMPtr<nsISchemaSimpleType> restriction;
|
|
|
|
restrictionInst = new nsSchemaRestrictionType(aSchema, aName);
|
|
if (!restrictionInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
restriction = restrictionInst;
|
|
|
|
nsCOMPtr<nsISchemaType> baseType;
|
|
nsAutoString baseStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
|
|
if (baseStr.Length() > 0) {
|
|
rv = GetNewOrUsedType(aSchema, aElement, baseStr,
|
|
getter_AddRefs(baseType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsISchemaSimpleType> simpleBase(do_QueryInterface(baseType));
|
|
if (!simpleBase) {
|
|
return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
|
|
}
|
|
rv = restrictionInst->SetBaseType(simpleBase);
|
|
}
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if ((tagName == nsSchemaAtoms::sSimpleType_atom) &&
|
|
!baseType) {
|
|
nsCOMPtr<nsISchemaSimpleType> simpleType;
|
|
|
|
rv = ProcessSimpleType(aSchema, childElement,
|
|
getter_AddRefs(simpleType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = restrictionInst->SetBaseType(simpleType);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
baseType = simpleType;
|
|
}
|
|
else if ((tagName == nsSchemaAtoms::sMinExclusive_atom) ||
|
|
(tagName == nsSchemaAtoms::sMinInclusive_atom) ||
|
|
(tagName == nsSchemaAtoms::sMaxExclusive_atom) ||
|
|
(tagName == nsSchemaAtoms::sMaxInclusive_atom) ||
|
|
(tagName == nsSchemaAtoms::sTotalDigits_atom) ||
|
|
(tagName == nsSchemaAtoms::sFractionDigits_atom) ||
|
|
(tagName == nsSchemaAtoms::sLength_atom) ||
|
|
(tagName == nsSchemaAtoms::sMinLength_atom) ||
|
|
(tagName == nsSchemaAtoms::sMaxLength_atom) ||
|
|
(tagName == nsSchemaAtoms::sEnumeration_atom) ||
|
|
(tagName == nsSchemaAtoms::sWhiteSpace_atom) ||
|
|
(tagName == nsSchemaAtoms::sPattern_atom)) {
|
|
nsCOMPtr<nsISchemaFacet> facet;
|
|
|
|
rv = ProcessFacet(aSchema, childElement,
|
|
tagName, getter_AddRefs(facet));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = restrictionInst->AddFacet(facet);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
*aSimpleType = restriction;
|
|
NS_ADDREF(*aSimpleType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleTypeList(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
const nsAReadableString& aName,
|
|
nsISchemaSimpleType** aSimpleType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsSchemaListType* listInst;
|
|
nsCOMPtr<nsISchemaSimpleType> list;
|
|
|
|
listInst = new nsSchemaListType(aSchema, aName);
|
|
if (!listInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
list = listInst;
|
|
|
|
nsAutoString itemTypeStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("itemType"), itemTypeStr);
|
|
|
|
nsCOMPtr<nsISchemaSimpleType> itemType;
|
|
if (itemTypeStr.Length() > 0) {
|
|
nsCOMPtr<nsISchemaType> type;
|
|
rv = GetNewOrUsedType(aSchema, aElement, itemTypeStr,
|
|
getter_AddRefs(type));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
itemType = do_QueryInterface(type);
|
|
}
|
|
else {
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sSimpleType_atom) {
|
|
rv = ProcessSimpleType(aSchema, childElement,
|
|
getter_AddRefs(itemType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!itemType) {
|
|
return NS_ERROR_SCHEMA_MISSING_TYPE;
|
|
}
|
|
listInst->SetListType(itemType);
|
|
|
|
*aSimpleType = list;
|
|
NS_ADDREF(*aSimpleType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleTypeUnion(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
const nsAReadableString& aName,
|
|
nsISchemaSimpleType** aSimpleType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsSchemaUnionType* unionInst;
|
|
nsCOMPtr<nsISchemaSimpleType> unionType;
|
|
|
|
unionInst = new nsSchemaUnionType(aSchema, aName);
|
|
if (!unionInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
unionType = unionInst;
|
|
|
|
nsCOMPtr<nsISchemaSimpleType> memberType;
|
|
nsAutoString memberTypes;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("memberTypes"), memberTypes);
|
|
if (memberTypes.Length() > 0) {
|
|
nsReadingIterator<PRUnichar> begin, end, tokenEnd;
|
|
|
|
memberTypes.BeginReading(tokenEnd);
|
|
memberTypes.EndReading(end);
|
|
|
|
while (tokenEnd != end) {
|
|
nsAutoString typeStr;
|
|
begin = tokenEnd;
|
|
if (FindCharInReadable(PRUnichar(' '), tokenEnd, end)) {
|
|
CopyUnicodeTo(begin, tokenEnd, typeStr);
|
|
++tokenEnd;
|
|
}
|
|
else {
|
|
CopyUnicodeTo(begin, end, typeStr);
|
|
}
|
|
|
|
nsCOMPtr<nsISchemaType> type;
|
|
rv = GetNewOrUsedType(aSchema, aElement, typeStr,
|
|
getter_AddRefs(type));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
memberType = do_QueryInterface(type);
|
|
if (!memberType) {
|
|
return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
|
|
}
|
|
|
|
rv = unionInst->AddUnionType(memberType);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sSimpleType_atom) {
|
|
rv = ProcessSimpleType(aSchema, childElement,
|
|
getter_AddRefs(memberType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = unionInst->AddUnionType(memberType);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
*aSimpleType = unionType;
|
|
NS_ADDREF(*aSimpleType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessModelGroup(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsIAtom* aTagName,
|
|
nsSchemaModelGroup* aParentSequence,
|
|
nsISchemaModelGroup** aModelGroup)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsISchemaModelGroup> modelGroup;
|
|
PRUint32 minOccurs, maxOccurs;
|
|
GetMinAndMax(aElement, &minOccurs, &maxOccurs);
|
|
|
|
// Check for a ref attribute
|
|
nsAutoString ref;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
|
|
|
|
if ((aTagName == nsSchemaAtoms::sModelGroup_atom) &&
|
|
(ref.Length() > 0)) {
|
|
nsSchemaModelGroupRef* modelGroupRef = new nsSchemaModelGroupRef(aSchema,
|
|
ref);
|
|
if (!modelGroupRef) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
modelGroup = modelGroupRef;
|
|
|
|
modelGroupRef->SetMinOccurs(minOccurs);
|
|
modelGroupRef->SetMaxOccurs(maxOccurs);
|
|
}
|
|
else {
|
|
nsAutoString name;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName = aTagName;
|
|
|
|
// If this is a group element, find the first compositor
|
|
// child and continue with that.
|
|
if (aTagName == nsSchemaAtoms::sModelGroup_atom) {
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if ((tagName == nsSchemaAtoms::sAll_atom) ||
|
|
(tagName == nsSchemaAtoms::sChoice_atom) ||
|
|
(tagName == nsSchemaAtoms::sSequence_atom)) {
|
|
iterator.SetElement(childElement);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
nsSchemaModelGroup* modelGroupInst;
|
|
|
|
// If we have a parent sequence and we're a sequence that
|
|
// only appears once, then collapse us.
|
|
if (aParentSequence &&
|
|
(tagName == nsSchemaAtoms::sSequence_atom) &&
|
|
(minOccurs == 1) && (maxOccurs == 1)) {
|
|
modelGroupInst = aParentSequence;
|
|
modelGroup = modelGroupInst;
|
|
}
|
|
else {
|
|
modelGroupInst = new nsSchemaModelGroup(aSchema, name);
|
|
if (!modelGroupInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
modelGroup = modelGroupInst;
|
|
|
|
modelGroupInst->SetMinOccurs(minOccurs);
|
|
modelGroupInst->SetMaxOccurs(maxOccurs);
|
|
|
|
|
|
if (tagName == nsSchemaAtoms::sAll_atom) {
|
|
modelGroupInst->SetCompositor(nsISchemaModelGroup::COMPOSITOR_ALL);
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sChoice_atom) {
|
|
modelGroupInst->SetCompositor(nsISchemaModelGroup::COMPOSITOR_CHOICE);
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sSequence_atom) {
|
|
modelGroupInst->SetCompositor(nsISchemaModelGroup::COMPOSITOR_SEQUENCE);
|
|
}
|
|
}
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName != nsSchemaAtoms::sAnnotation_atom) {
|
|
nsCOMPtr<nsISchemaParticle> particle;
|
|
|
|
rv = ProcessParticle(aSchema, childElement,
|
|
tagName, getter_AddRefs(particle));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = modelGroupInst->AddParticle(particle);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*aModelGroup = modelGroup;
|
|
NS_ADDREF(*aModelGroup);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessParticle(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsIAtom* aTagName,
|
|
nsISchemaParticle** aParticle)
|
|
{
|
|
nsresult rv;
|
|
|
|
if (aTagName == nsSchemaAtoms::sElement_atom) {
|
|
nsCOMPtr<nsISchemaElement> element;
|
|
|
|
rv = ProcessElement(aSchema, aElement, getter_AddRefs(element));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
*aParticle = element;
|
|
NS_IF_ADDREF(*aParticle);
|
|
}
|
|
else if ((aTagName == nsSchemaAtoms::sModelGroup_atom) ||
|
|
(aTagName == nsSchemaAtoms::sChoice_atom) ||
|
|
(aTagName == nsSchemaAtoms::sSequence_atom)) {
|
|
nsCOMPtr<nsISchemaModelGroup> modelGroup;
|
|
|
|
rv = ProcessModelGroup(aSchema, aElement,
|
|
aTagName, nsnull, getter_AddRefs(modelGroup));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
*aParticle = modelGroup;
|
|
NS_IF_ADDREF(*aParticle);
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sAny_atom) {
|
|
|
|
nsCOMPtr<nsISchemaParticle> anyParticle;
|
|
nsSchemaAnyParticle* anyParticleInst = new nsSchemaAnyParticle(aSchema);
|
|
if (!anyParticleInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
anyParticle = anyParticleInst;
|
|
|
|
PRUint32 minOccurs, maxOccurs;
|
|
GetMinAndMax(aElement, &minOccurs, &maxOccurs);
|
|
anyParticleInst->SetMinOccurs(minOccurs);
|
|
anyParticleInst->SetMaxOccurs(maxOccurs);
|
|
|
|
PRUint16 process;
|
|
GetProcess(aElement, &process);
|
|
anyParticleInst->SetProcess(process);
|
|
|
|
nsAutoString namespaceStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("namespace"), namespaceStr);
|
|
anyParticleInst->SetNamespace(namespaceStr);
|
|
|
|
*aParticle = anyParticle;
|
|
NS_ADDREF(*aParticle);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessAttributeComponent(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsIAtom* aTagName,
|
|
nsISchemaAttributeComponent** aAttribute)
|
|
{
|
|
nsresult rv;
|
|
|
|
if (aTagName == nsSchemaAtoms::sAttribute_atom) {
|
|
nsCOMPtr<nsISchemaAttribute> attribute;
|
|
|
|
rv = ProcessAttribute(aSchema, aElement,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
*aAttribute = attribute;
|
|
NS_IF_ADDREF(*aAttribute);
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sAttributeGroup_atom) {
|
|
nsCOMPtr<nsISchemaAttributeGroup> attributeGroup;
|
|
|
|
rv = ProcessAttributeGroup(aSchema, aElement,
|
|
getter_AddRefs(attributeGroup));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
*aAttribute = attributeGroup;
|
|
NS_IF_ADDREF(*aAttribute);
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sAnyAttribute_atom) {
|
|
nsCOMPtr<nsISchemaAttributeComponent> anyAttribute;
|
|
nsSchemaAnyAttribute* anyAttributeInst = new nsSchemaAnyAttribute(aSchema);
|
|
if (!anyAttributeInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
anyAttribute = anyAttributeInst;
|
|
|
|
PRUint16 process;
|
|
GetProcess(aElement, &process);
|
|
anyAttributeInst->SetProcess(process);
|
|
|
|
nsAutoString namespaceStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("namespace"), namespaceStr);
|
|
anyAttributeInst->SetNamespace(namespaceStr);
|
|
|
|
*aAttribute = anyAttribute;
|
|
NS_ADDREF(*aAttribute);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessAttribute(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISchemaAttribute** aAttribute)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsISchemaAttribute> attribute;
|
|
|
|
nsAutoString defaultValue, fixedValue;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("default"), defaultValue);
|
|
aElement->GetAttribute(NS_LITERAL_STRING("fixed"), fixedValue);
|
|
|
|
PRUint16 use;
|
|
GetUse(aElement, &use);
|
|
|
|
nsAutoString ref;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
|
|
if (ref.Length() > 0) {
|
|
nsSchemaAttributeRef* attributeRef = new nsSchemaAttributeRef(aSchema,
|
|
ref);
|
|
if (!attributeRef) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
attribute = attributeRef;
|
|
|
|
attributeRef->SetConstraints(defaultValue, fixedValue);
|
|
attributeRef->SetUse(use);
|
|
}
|
|
else {
|
|
nsAutoString name;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
|
|
|
|
nsSchemaAttribute* attributeInst = new nsSchemaAttribute(aSchema,
|
|
name);
|
|
if (!attributeInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
attribute = attributeInst;
|
|
|
|
attributeInst->SetConstraints(defaultValue, fixedValue);
|
|
attributeInst->SetUse(use);
|
|
|
|
nsCOMPtr<nsISchemaSimpleType> simpleType;
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sSimpleType_atom) {
|
|
rv = ProcessSimpleType(aSchema, childElement,
|
|
getter_AddRefs(simpleType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!simpleType) {
|
|
nsAutoString typeStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("type"), typeStr);
|
|
|
|
if (typeStr.Length() > 0) {
|
|
nsCOMPtr<nsISchemaType> schemaType;
|
|
rv = GetNewOrUsedType(aSchema, aElement, typeStr,
|
|
getter_AddRefs(schemaType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
simpleType = do_QueryInterface(schemaType);
|
|
if (!simpleType) {
|
|
return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
|
|
}
|
|
}
|
|
}
|
|
|
|
attributeInst->SetType(simpleType);
|
|
}
|
|
|
|
*aAttribute = attribute;
|
|
NS_ADDREF(*aAttribute);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessAttributeGroup(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISchemaAttributeGroup** aAttributeGroup)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsISchemaAttributeGroup> attributeGroup;
|
|
|
|
nsAutoString ref;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
|
|
|
|
if (ref.Length() > 0) {
|
|
nsSchemaAttributeGroupRef* attrRef = new nsSchemaAttributeGroupRef(aSchema,
|
|
ref);
|
|
if (!attrRef) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
attributeGroup = attrRef;
|
|
}
|
|
else {
|
|
nsAutoString name;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
|
|
|
|
nsSchemaAttributeGroup* attrInst = new nsSchemaAttributeGroup(aSchema,
|
|
name);
|
|
if (!attrInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
attributeGroup = attrInst;
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
|
|
(tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
|
|
(tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
|
|
nsCOMPtr<nsISchemaAttributeComponent> attribute;
|
|
|
|
rv = ProcessAttributeComponent(aSchema,
|
|
childElement, tagName,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = attrInst->AddAttribute(attribute);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*aAttributeGroup = attributeGroup;
|
|
NS_ADDREF(*aAttributeGroup);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessFacet(nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsIAtom* aTagName,
|
|
nsISchemaFacet** aFacet)
|
|
{
|
|
PRInt32 rv;
|
|
|
|
nsCOMPtr<nsISchemaFacet> facet;
|
|
nsSchemaFacet* facetInst = new nsSchemaFacet(aSchema);
|
|
if (!facetInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
facet = facetInst;
|
|
|
|
PRUint16 facetType;
|
|
if (aTagName == nsSchemaAtoms::sLength_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_LENGTH;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMinLength_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_MINLENGTH;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMaxLength_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_MAXLENGTH;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sPattern_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_PATTERN;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sEnumeration_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_ENUMERATION;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sWhiteSpace_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_WHITESPACE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMaxInclusive_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_MAXINCLUSIVE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMinInclusive_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_MININCLUSIVE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMaxExclusive_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_MAXEXCLUSIVE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMaxInclusive_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_MINEXCLUSIVE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sTotalDigits_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_TOTALDIGITS;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sFractionDigits_atom) {
|
|
facetType = nsISchemaFacet::FACET_TYPE_FRACTIONDIGITS;
|
|
}
|
|
else {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
facetInst->SetFacetType(facetType);
|
|
|
|
nsAutoString valueStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("value"), valueStr);
|
|
if (valueStr.Length() == 0) {
|
|
return NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
|
|
}
|
|
|
|
if ((aTagName == nsSchemaAtoms::sLength_atom) ||
|
|
(aTagName == nsSchemaAtoms::sMinLength_atom) ||
|
|
(aTagName == nsSchemaAtoms::sMaxLength_atom) ||
|
|
(aTagName == nsSchemaAtoms::sTotalDigits_atom) ||
|
|
(aTagName == nsSchemaAtoms::sFractionDigits_atom)) {
|
|
PRInt32 intVal = valueStr.ToInteger(&rv);
|
|
|
|
if (NS_FAILED(rv) ||
|
|
(intVal < 0) ||
|
|
((aTagName == nsSchemaAtoms::sTotalDigits_atom) && (intVal == 0))) {
|
|
return NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
|
|
}
|
|
|
|
facetInst->SetUintValue((PRUint32)intVal);
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sWhiteSpace_atom) {
|
|
PRUint16 whiteSpaceVal;
|
|
if (valueStr.Equals(NS_LITERAL_STRING("collapse"))) {
|
|
whiteSpaceVal = nsSchemaFacet::WHITESPACE_COLLAPSE;
|
|
}
|
|
else if (valueStr.Equals(NS_LITERAL_STRING("preserve"))) {
|
|
whiteSpaceVal = nsSchemaFacet::WHITESPACE_PRESERVE;
|
|
}
|
|
else if (valueStr.Equals(NS_LITERAL_STRING("replace"))) {
|
|
whiteSpaceVal = nsSchemaFacet::WHITESPACE_REPLACE;
|
|
}
|
|
else {
|
|
return NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
|
|
}
|
|
|
|
facetInst->SetWhitespaceValue(whiteSpaceVal);
|
|
}
|
|
else {
|
|
facetInst->SetValue(valueStr);
|
|
}
|
|
|
|
nsAutoString isFixed;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("fixed"), isFixed);
|
|
facetInst->SetIsFixed(isFixed.Equals(NS_LITERAL_STRING("true")));
|
|
|
|
*aFacet = facet;
|
|
NS_ADDREF(*aFacet);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsSchemaLoader::GetUse(nsIDOMElement* aElement,
|
|
PRUint16* aUse)
|
|
{
|
|
*aUse = nsISchemaAttribute::USE_OPTIONAL;
|
|
|
|
nsAutoString use;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("use"), use);
|
|
|
|
if (use.Equals(NS_LITERAL_STRING("prohibited"))) {
|
|
*aUse = nsISchemaAttribute::USE_PROHIBITED;
|
|
}
|
|
else if (use.Equals(NS_LITERAL_STRING("required"))) {
|
|
*aUse = nsISchemaAttribute::USE_REQUIRED;
|
|
}
|
|
}
|
|
|
|
void
|
|
nsSchemaLoader::GetProcess(nsIDOMElement* aElement,
|
|
PRUint16* aProcess)
|
|
{
|
|
*aProcess = nsISchemaAnyParticle::PROCESS_STRICT;
|
|
|
|
nsAutoString process;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("process"), process);
|
|
|
|
if (process.Equals(NS_LITERAL_STRING("lax"))) {
|
|
*aProcess = nsISchemaAnyParticle::PROCESS_LAX;
|
|
}
|
|
else if (process.Equals(NS_LITERAL_STRING("skip"))) {
|
|
*aProcess = nsISchemaAnyParticle::PROCESS_SKIP;
|
|
}
|
|
}
|
|
|
|
void
|
|
nsSchemaLoader::GetMinAndMax(nsIDOMElement* aElement,
|
|
PRUint32* aMinOccurs,
|
|
PRUint32* aMaxOccurs)
|
|
{
|
|
*aMinOccurs = 1;
|
|
*aMaxOccurs = 1;
|
|
|
|
nsAutoString minStr, maxStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("minOccurs"), minStr);
|
|
aElement->GetAttribute(NS_LITERAL_STRING("maxOccurs"), maxStr);
|
|
|
|
PRInt32 rv;
|
|
if (minStr.Length() > 0) {
|
|
PRInt32 minVal = minStr.ToInteger(&rv);
|
|
if (NS_SUCCEEDED(rv) && (minVal >= 0)) {
|
|
*aMinOccurs = (PRUint32)minVal;
|
|
}
|
|
}
|
|
|
|
if (maxStr.Length() > 0) {
|
|
if (maxStr.Equals(NS_LITERAL_STRING("unbounded"))) {
|
|
*aMaxOccurs = nsISchemaParticle::OCCURRENCE_UNBOUNDED;
|
|
}
|
|
else {
|
|
PRInt32 maxVal = maxStr.ToInteger(&rv);
|
|
if (NS_SUCCEEDED(rv) && (maxVal >= 0)) {
|
|
*aMaxOccurs = (PRUint32)maxVal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|