3446 lines
110 KiB
C++
3446 lines
110 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* 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 the Initial Developer are Copyright (C) 2001
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Vidur Apparao <vidur@netscape.com> (original author)
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include "nsSchemaPrivate.h"
|
|
#include "nsSchemaLoader.h"
|
|
#include "nsISVSchemaErrorHandler.h"
|
|
|
|
// content includes
|
|
#include "nsIContent.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsIDOMDocument.h"
|
|
#include "nsIDOM3Node.h"
|
|
|
|
// loading includes
|
|
#include "nsIXMLHttpRequest.h"
|
|
#include "nsIDOMEvent.h"
|
|
#include "nsIDOMEventListener.h"
|
|
#include "nsIDOMEventTarget.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsIParserService.h"
|
|
|
|
// XPConnect includes
|
|
#include "nsIXPConnect.h"
|
|
#include "nsIScriptSecurityManager.h"
|
|
#include "nsIPrincipal.h"
|
|
|
|
// XPCOM includes
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIComponentManager.h"
|
|
#include "nsStaticAtom.h"
|
|
#include "nsIAtomService.h"
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// nsSchemaAtoms implementation
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
|
|
// define storage for all atoms
|
|
#define SCHEMA_ATOM(_name, _value) nsIAtom* nsSchemaAtoms::_name;
|
|
#include "nsSchemaAtomList.h"
|
|
#undef SCHEMA_ATOM
|
|
|
|
static const nsStaticAtom atomInfo[] = {
|
|
#define SCHEMA_ATOM(_name, _value) { _value, &nsSchemaAtoms::_name },
|
|
#include "nsSchemaAtomList.h"
|
|
#undef SCHEMA_ATOM
|
|
};
|
|
|
|
nsresult
|
|
nsSchemaAtoms::AddRefAtoms()
|
|
{
|
|
nsresult rv;
|
|
PRUint32 numAtoms = NS_ARRAY_LENGTH(atomInfo);
|
|
nsCOMPtr<nsIAtomService> atomServ = do_GetService(NS_ATOMSERVICE_CONTRACTID,
|
|
&rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
for (PRUint32 i = 0; i < numAtoms; ++i) {
|
|
atomServ->GetPermanentAtomUTF8(atomInfo[i].mString,
|
|
atomInfo[i].mAtom);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadListener implementation
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
|
|
class LoadListener : public nsIDOMEventListener {
|
|
public:
|
|
LoadListener(nsSchemaLoader* aLoader,
|
|
nsISVSchemaLoadListener* aListener,
|
|
nsIXMLHttpRequest* aRequest);
|
|
virtual ~LoadListener();
|
|
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIDOMEVENTLISTENER
|
|
|
|
private:
|
|
nsSchemaLoader* mLoader;
|
|
nsCOMPtr<nsISVSchemaLoadListener> mListener;
|
|
nsCOMPtr<nsIXMLHttpRequest> mRequest;
|
|
nsString mURI;
|
|
};
|
|
|
|
LoadListener::LoadListener(nsSchemaLoader* aLoader,
|
|
nsISVSchemaLoadListener* aListener,
|
|
nsIXMLHttpRequest* aRequest)
|
|
{
|
|
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;
|
|
|
|
PRUint32 httpStatus;
|
|
mRequest->GetStatus(&httpStatus);
|
|
|
|
nsCOMPtr<nsISVSchema> schema;
|
|
|
|
nsAutoString eventType;
|
|
event->GetType(eventType);
|
|
|
|
PRBool succeeded = (httpStatus / 100 == 2);
|
|
|
|
// if we loaded fine, and not http/https, we assume success in loaded the file.
|
|
if (!succeeded && eventType.EqualsLiteral("load")) {
|
|
nsCOMPtr<nsIChannel> channel;
|
|
mRequest->GetChannel(getter_AddRefs(channel));
|
|
if (channel) {
|
|
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
|
|
|
// if qi to httpChannel fails, it isn't a http:// or https:// request
|
|
if (!httpChannel) {
|
|
succeeded = PR_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (succeeded && eventType.EqualsLiteral("load")) {
|
|
nsCOMPtr<nsIDOMDocument> document;
|
|
|
|
rv = mRequest->GetResponseXML(getter_AddRefs(document));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsCOMPtr<nsIDOMElement> element;
|
|
|
|
if (document)
|
|
document->GetDocumentElement(getter_AddRefs(element));
|
|
|
|
//XXXTelemac TODO Use an nsISVSchemaErrorHandler instead of nsnull
|
|
if (element)
|
|
rv = mLoader->ProcessSchemaElement(element, nsnull, getter_AddRefs(schema));
|
|
else
|
|
rv = NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
|
|
}
|
|
}
|
|
else {
|
|
rv = NS_ERROR_SCHEMA_LOADING_ERROR;
|
|
}
|
|
|
|
//XXXTelemac OnError call replace by use of nsISVSchemaErrorHandler
|
|
//XXXTelemac in sub-processing methods.
|
|
|
|
if (mListener) {
|
|
if (NS_SUCCEEDED(rv))
|
|
mListener->OnLoad(schema);
|
|
else
|
|
mListener->OnError(rv, NS_LITERAL_STRING("Failure loading"));
|
|
}
|
|
|
|
NS_IF_RELEASE(mLoader);
|
|
mListener = nsnull;
|
|
mRequest = nsnull;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// nsBuiltinSchemaCollection implementation
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
nsBuiltinSchemaCollection::nsBuiltinSchemaCollection()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
nsBuiltinSchemaCollection::Init()
|
|
{
|
|
return (mBuiltinTypesHash.Init() && mSOAPTypeHash.Init()) ? NS_OK
|
|
: NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS1(nsBuiltinSchemaCollection,
|
|
nsISVSchemaCollection)
|
|
|
|
/* nsISVSchema getSchema (in AString targetNamespace); */
|
|
NS_IMETHODIMP
|
|
nsBuiltinSchemaCollection::GetSchema(const nsAString & targetNamespace,
|
|
nsISVSchema **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
return NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
|
|
}
|
|
|
|
/* nsISVSchemaElement getElement (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsBuiltinSchemaCollection::GetElement(const nsAString & aName,
|
|
const nsAString & aNamespace,
|
|
nsISVSchemaElement **_retval)
|
|
{
|
|
if (aNamespace.IsEmpty()) {
|
|
NS_WARNING("nsSchemaLoader::GetSchema(nsAString,nsISVSchema): "
|
|
"Invalid |targetNamespace| is empty");
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
/* nsISVSchemaAttribute getAttribute (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsBuiltinSchemaCollection::GetAttribute(const nsAString & aName,
|
|
const nsAString & aNamespace,
|
|
nsISVSchemaAttribute **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
*_retval = nsnull;
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
static PRBool
|
|
IsSchemaNamespace(const nsAString& aNamespace)
|
|
{
|
|
if (aNamespace.EqualsLiteral(NS_SCHEMA_2001_NAMESPACE) ||
|
|
aNamespace.EqualsLiteral(NS_SCHEMA_1999_NAMESPACE)) {
|
|
return PR_TRUE;
|
|
}
|
|
else {
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
|
|
static PRBool
|
|
IsSOAPNamespace(const nsAString& aNamespace)
|
|
{
|
|
if (aNamespace.EqualsLiteral(NS_SOAP_1_1_ENCODING_NAMESPACE) ||
|
|
aNamespace.EqualsLiteral(NS_SOAP_1_2_ENCODING_NAMESPACE)) {
|
|
return PR_TRUE;
|
|
}
|
|
else {
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
|
|
/* nsISVSchemaType getType (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsBuiltinSchemaCollection::GetType(const nsAString & aName,
|
|
const nsAString & aNamespace,
|
|
nsISVSchemaType **_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 nsAString& aName,
|
|
const nsAString& aNamespace,
|
|
nsISVSchemaType** aType)
|
|
{
|
|
if (!mBuiltinTypesHash.Get(aName, aType)) {
|
|
nsresult rv;
|
|
nsCOMPtr<nsIAtomService> atomServ =
|
|
do_GetService(NS_ATOMSERVICE_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIAtom> typeName;
|
|
rv = atomServ->GetAtom(aName.BeginReading(), getter_AddRefs(typeName));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
PRUint16 typeVal;
|
|
if (typeName == nsSchemaAtoms::sAnyType_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_ANYTYPE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sString_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_STRING;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNormalizedString_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sToken_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_TOKEN;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sByte_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_BYTE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sUnsignedByte_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sBase64Binary_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sHexBinary_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_HEXBINARY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sInteger_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_INTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sPositiveInteger_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNegativeInteger_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNonnegativeInteger_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNonpositiveInteger_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sInt_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_INT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sUnsignedInt_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sLong_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_LONG;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sUnsignedLong_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sShort_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_SHORT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sUnsignedShort_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDecimal_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_DECIMAL;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sFloat_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_FLOAT;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDouble_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_DOUBLE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sBoolean_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_BOOLEAN;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sTime_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_TIME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDateTime_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_DATETIME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDuration_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_DURATION;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sDate_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_DATE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGMonth_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_GMONTH;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGYear_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_GYEAR;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGYearMonth_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGDay_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_GDAY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sGMonthDay_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sName_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_NAME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sQName_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_QNAME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNCName_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_NCNAME;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sAnyURI_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_ANYURI;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sLanguage_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_LANGUAGE;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sID_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_ID;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sIDREF_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_IDREF;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sIDREFS_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_IDREFS;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sENTITY_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_ENTITY;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sENTITIES_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_ENTITIES;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNOTATION_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_NOTATION;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNMTOKEN_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_NMTOKEN;
|
|
}
|
|
else if (typeName == nsSchemaAtoms::sNMTOKENS_atom) {
|
|
typeVal = nsISVSchemaBuiltinType::BUILTIN_TYPE_NMTOKENS;
|
|
}
|
|
else {
|
|
NS_ERROR("Unknown builtin type");
|
|
return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
|
|
}
|
|
|
|
nsCOMPtr<nsISVSchemaType> builtin = new nsSchemaBuiltinType(typeVal);
|
|
if (!builtin) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
mBuiltinTypesHash.Put(aName, builtin);
|
|
builtin.swap(*aType);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsBuiltinSchemaCollection::GetSOAPType(const nsAString& aName,
|
|
const nsAString& aNamespace,
|
|
nsISVSchemaType** aType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (!mSOAPTypeHash.Get(aName, aType)) {
|
|
if (aName.EqualsLiteral("Array")) {
|
|
nsCOMPtr<nsISVSchemaType> 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;
|
|
}
|
|
|
|
mSOAPTypeHash.Put(aName, array);
|
|
|
|
*aType = array;
|
|
NS_ADDREF(*aType);
|
|
}
|
|
else if (aName.EqualsLiteral("arrayType")) {
|
|
nsSOAPArrayType* arrayType = new nsSOAPArrayType();
|
|
if (!arrayType) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
mSOAPTypeHash.Put(aName, arrayType);
|
|
|
|
*aType = arrayType;
|
|
NS_ADDREF(*aType);
|
|
}
|
|
else {
|
|
rv = NS_ERROR_SCHEMA_UNKNOWN_TYPE;
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// nsSchemaLoader implementation
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
|
|
nsSchemaLoader::nsSchemaLoader()
|
|
{
|
|
mBuiltinCollection = do_GetService(NS_SVBUILTINSCHEMACOLLECTION_CONTRACTID);
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::Init()
|
|
{
|
|
return mSchemas.Init() ? NS_OK : NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS2(nsSchemaLoader,
|
|
nsISVSchemaLoader,
|
|
nsISVSchemaCollection)
|
|
|
|
|
|
/* nsISVSchema getSchema (in AString targetNamespace); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::GetSchema(const nsAString & targetNamespace,
|
|
nsISVSchema ** aResult)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
return mSchemas.Get(targetNamespace, aResult) ? NS_OK :
|
|
NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
|
|
}
|
|
|
|
/* nsISVSchemaElement getElement (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::GetElement(const nsAString & aName,
|
|
const nsAString & aNamespace,
|
|
nsISVSchemaElement **_retval)
|
|
{
|
|
nsCOMPtr<nsISVSchema> schema;
|
|
nsresult rv = GetSchema(aNamespace, getter_AddRefs(schema));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
return schema->GetElementByName(aName, _retval);
|
|
}
|
|
|
|
/* nsISVSchemaAttribute getAttribute (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::GetAttribute(const nsAString & aName,
|
|
const nsAString & aNamespace,
|
|
nsISVSchemaAttribute **_retval)
|
|
{
|
|
nsCOMPtr<nsISVSchema> schema;
|
|
nsresult rv = GetSchema(aNamespace, getter_AddRefs(schema));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
return schema->GetAttributeByName(aName, _retval);
|
|
}
|
|
|
|
/* nsISVSchemaType getType (in AString name, in AString namespace); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::GetType(const nsAString & aName,
|
|
const nsAString & aNamespace,
|
|
nsISVSchemaType **_retval)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (IsSchemaNamespace(aNamespace) || IsSOAPNamespace(aNamespace)) {
|
|
rv = mBuiltinCollection->GetType(aName, aNamespace, _retval);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg(NS_LITERAL_STRING("nsSchemaLoader::GetType: "));
|
|
errorMsg.AppendLiteral("Failure processing schema: cannot get schema type \"");
|
|
errorMsg.Append(aName);
|
|
errorMsg.AppendLiteral("\"");
|
|
NS_ERROR(NS_ConvertUTF16toUTF8(errorMsg).get());
|
|
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsISVSchema> schema;
|
|
rv = GetSchema(aNamespace, getter_AddRefs(schema));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = schema->GetTypeByName(aName, _retval);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString msg(NS_LITERAL_STRING("nsSchemaLoader::GetType: "));
|
|
msg.AppendLiteral("Failure processing schema: ");
|
|
msg.AppendLiteral("cannot get schema type \"");
|
|
msg.Append(aName);
|
|
msg.AppendLiteral("\"");
|
|
NS_ERROR(NS_ConvertUTF16toUTF8(msg).get());
|
|
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::GetResolvedURI(const nsAString& aSchemaURI,
|
|
const char* aMethod,
|
|
nsIURI** aURI)
|
|
{
|
|
nsresult rv;
|
|
nsAXPCNativeCallContext *cc = nsnull;
|
|
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = xpc->GetCurrentNativeCallContext(&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)) {
|
|
principal->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;
|
|
}
|
|
|
|
/* nsISVSchema load (in AString schemaURI); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::Load(const nsAString& schemaURI,
|
|
nsISVSchema **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
nsCOMPtr<nsIDOMDocument> document;
|
|
nsresult rv = GetDocumentFromURI(schemaURI, getter_AddRefs(document));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (!document)
|
|
return NS_ERROR_SCHEMA_LOADING_ERROR;
|
|
|
|
nsCOMPtr<nsIDOMElement> element;
|
|
document->GetDocumentElement(getter_AddRefs(element));
|
|
if (element) {
|
|
//XXXTelemac TODO Have an error handler there instead or nsnull
|
|
rv = ProcessSchemaElement(element, nsnull, _retval);
|
|
}
|
|
else {
|
|
rv = NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* [noscript] void loadAsyncWithPrincipal (in AString schemaURI,
|
|
* in nsISVSchemaLoadListener listener,
|
|
* in nsIPrincipal principal);
|
|
*/
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::LoadAsyncWithPrincipal(const nsAString& schemaURI,
|
|
nsISVSchemaLoadListener *aListener,
|
|
nsIPrincipal *aPrincipal)
|
|
{
|
|
NS_ENSURE_ARG(aListener);
|
|
NS_ENSURE_ARG(aPrincipal);
|
|
|
|
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->Init(aPrincipal, nsnull, nsnull);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
const nsAString& empty = EmptyString();
|
|
rv = request->OpenRequest(NS_LITERAL_CSTRING("GET"), spec, PR_TRUE, empty,
|
|
empty);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
// Force the mimetype of the returned stream to be xml.
|
|
rv = request->OverrideMimeType(NS_LITERAL_CSTRING("application/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;
|
|
}
|
|
|
|
/* void loadAsync(in AString schemaURI, in nsISVSchemaLoadListener listener); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::LoadAsync(const nsAString& aSchemaURI,
|
|
nsISVSchemaLoadListener *aListener)
|
|
{
|
|
// Get the subject principal from the security manager. We need it to
|
|
// initialize the nsIXMLHttpRequest inside loadAsyncWithPrincipal.
|
|
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
|
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
|
|
NS_ENSURE_STATE(secMan);
|
|
|
|
nsCOMPtr<nsIPrincipal> principal;
|
|
nsresult rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
|
|
|
|
return LoadAsyncWithPrincipal(aSchemaURI, aListener, principal);
|
|
}
|
|
|
|
static const char* kSchemaNamespaces[] = {NS_SCHEMA_1999_NAMESPACE,
|
|
NS_SCHEMA_2001_NAMESPACE};
|
|
static PRUint32 kSchemaNamespacesLength = sizeof(kSchemaNamespaces) / sizeof(const char*);
|
|
|
|
/* nsISVSchema processSchemaElement (in nsIDOMElement element, in nsISVSchemaErrorHandler aErrorHandler); */
|
|
NS_IMETHODIMP
|
|
nsSchemaLoader::ProcessSchemaElement(nsIDOMElement* aElement,
|
|
nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsISVSchema **aResult)
|
|
{
|
|
NS_ENSURE_ARG(aElement);
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
nsRefPtr<nsSchema> schemaInst = new nsSchema(this, aElement);
|
|
if (!schemaInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
nsresult rv = schemaInst->Init();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString targetNamespace;
|
|
schemaInst->GetTargetNamespace(targetNamespace);
|
|
|
|
nsISVSchema * os;
|
|
if (mSchemas.Get(targetNamespace, &os)) {
|
|
*aResult = os;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces, kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
// For now, ignore the following
|
|
// annotations
|
|
// redefine
|
|
// notation
|
|
// identity-constraint elements
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sElement_atom) {
|
|
nsCOMPtr<nsISVSchemaElement> schemaElement;
|
|
rv = ProcessElement(aErrorHandler, schemaInst, childElement,
|
|
getter_AddRefs(schemaElement));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddElement(schemaElement);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sComplexType_atom) {
|
|
nsCOMPtr<nsISVSchemaComplexType> complexType;
|
|
rv = ProcessComplexType(aErrorHandler, schemaInst, childElement,
|
|
getter_AddRefs(complexType));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddType(complexType);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sSimpleType_atom) {
|
|
nsCOMPtr<nsISVSchemaSimpleType> simpleType;
|
|
rv = ProcessSimpleType(aErrorHandler, schemaInst, childElement,
|
|
getter_AddRefs(simpleType));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddType(simpleType);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sAttribute_atom) {
|
|
nsCOMPtr<nsISVSchemaAttribute> attribute;
|
|
rv = ProcessAttribute(aErrorHandler, schemaInst, childElement,
|
|
getter_AddRefs(attribute));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddAttribute(attribute);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sAttributeGroup_atom) {
|
|
nsCOMPtr<nsISVSchemaAttributeGroup> attributeGroup;
|
|
rv = ProcessAttributeGroup(aErrorHandler, schemaInst, childElement,
|
|
getter_AddRefs(attributeGroup));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddAttributeGroup(attributeGroup);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sModelGroup_atom) {
|
|
nsCOMPtr<nsISVSchemaModelGroup> modelGroup;
|
|
rv = ProcessModelGroup(aErrorHandler, schemaInst, childElement,
|
|
tagName, nsnull, getter_AddRefs(modelGroup));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = schemaInst->AddModelGroup(modelGroup);
|
|
}
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sInclude_atom ||
|
|
tagName == nsSchemaAtoms::sImport_atom) {
|
|
/* Mixing the handling of <include> and <import> as they are very similar,
|
|
other than a few requirements regarding namespaces.
|
|
|
|
http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-include
|
|
If we include a schema, it must either
|
|
(a) have the same targetNamespace as the including schema document or
|
|
(b) no targetNamespace at all
|
|
|
|
http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-import
|
|
When importing a schema, it must either
|
|
(a) if namespace is defined, then namespace == imported
|
|
targetNamespace
|
|
(b) if namespace is not defined, then imported schema must NOT
|
|
have a targetNamespace
|
|
|
|
If the uri to load doesn't resolve, it isn't a error. It is if its an
|
|
invalid XML document or not a schema file
|
|
*/
|
|
|
|
NS_NAMED_LITERAL_STRING(schemaLocationStr, "schemaLocation");
|
|
|
|
nsAutoString schemalocation;
|
|
childElement->GetAttribute(schemaLocationStr, schemalocation);
|
|
|
|
// if empty, skip it
|
|
if (schemalocation.IsEmpty())
|
|
continue;
|
|
|
|
nsCOMPtr<nsIIOService> ios = do_GetIOService();
|
|
NS_ENSURE_STATE(ios);
|
|
|
|
nsCOMPtr<nsIDOMDocument> document;
|
|
aElement->GetOwnerDocument(getter_AddRefs(document));
|
|
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
|
|
NS_ENSURE_STATE(doc);
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
rv = NS_NewURI(getter_AddRefs(uri),
|
|
NS_ConvertUTF16toUTF8(schemalocation),
|
|
doc->GetDocumentCharacterSet().get(),
|
|
doc->GetDocumentURI());
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_STATE(uri);
|
|
|
|
// since we could be going cross-domain, make sure we can load it by doing
|
|
// a principal same origin check.
|
|
|
|
// get the base document's principal
|
|
nsIPrincipal *basePrincipal = doc->NodePrincipal();
|
|
NS_ENSURE_STATE(basePrincipal);
|
|
|
|
// Do a same origin check on the principal
|
|
rv = basePrincipal->CheckMayLoad(uri, PR_TRUE);
|
|
if (NS_FAILED(rv))
|
|
continue;
|
|
|
|
// get the url
|
|
nsCAutoString spec;
|
|
uri->GetSpec(spec);
|
|
|
|
nsCOMPtr<nsIDOMDocument> includedDocument;
|
|
rv = GetDocumentFromURI(NS_ConvertUTF8toUTF16(spec),
|
|
getter_AddRefs(includedDocument));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// if no document, it is an error
|
|
NS_ENSURE_STATE(includedDocument);
|
|
|
|
// get the document element - it should be a xsd:schema
|
|
nsCOMPtr<nsIDOMElement> element;
|
|
includedDocument->GetDocumentElement(getter_AddRefs(element));
|
|
|
|
nsAutoString localName, nsUri;
|
|
element->GetLocalName(localName);
|
|
element->GetNamespaceURI(nsUri);
|
|
|
|
PRBool correctNamespace = PR_FALSE;
|
|
PRUint32 i;
|
|
for (i = 0; i < kSchemaNamespacesLength; i++) {
|
|
if (nsUri.Equals(NS_ConvertASCIItoUTF16(kSchemaNamespaces[i]))) {
|
|
correctNamespace = PR_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!correctNamespace || !localName.EqualsLiteral("schema")) {
|
|
// not a valid schema file
|
|
return NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
|
|
}
|
|
|
|
// XXX: check the target namespace requirements
|
|
|
|
// If <import>, simply call self to do all the heavy lifting
|
|
if (tagName == nsSchemaAtoms::sImport_atom) {
|
|
rv = ProcessSchemaElement(element, nsnull, aResult);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
continue;
|
|
}
|
|
|
|
// import/append all elements in the included file to our schema element
|
|
nsCOMPtr<nsIDOMDocument> ownerDoc;
|
|
rv = childElement->GetOwnerDocument(getter_AddRefs(ownerDoc));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_STATE(ownerDoc);
|
|
|
|
nsCOMPtr<nsIDOMNode> tmpNode, importedNode, dummy;
|
|
element->GetFirstChild(getter_AddRefs(tmpNode));
|
|
|
|
// get the child element's next sibling so we have something to insert
|
|
// before while we are appending to the current schema document
|
|
unsigned short nodeType;
|
|
nsCOMPtr<nsIDOMNode> nextSibling;
|
|
childElement->GetNextSibling(getter_AddRefs(nextSibling));
|
|
|
|
while (tmpNode) {
|
|
tmpNode->GetNodeType(&nodeType);
|
|
|
|
if (nodeType == nsIDOMNode::ELEMENT_NODE) {
|
|
rv = ownerDoc->ImportNode(tmpNode, PR_TRUE,
|
|
getter_AddRefs(importedNode));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// InsertBefore can deal with a null nextSibling (will append)
|
|
rv = aElement->InsertBefore(importedNode, nextSibling,
|
|
getter_AddRefs(dummy));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
tmpNode->GetNextSibling(getter_AddRefs(dummy));
|
|
tmpNode = dummy;
|
|
}
|
|
|
|
// we twidle the iterator (reset), making sure to point it at the right
|
|
// place. We do this because the iterator takes a snapshot the DOMList,
|
|
// so we tell it to reinit itself and then reset it to the original index.
|
|
PRUint32 index = iterator.GetCurrentIndex();
|
|
iterator.SetElement(aElement);
|
|
iterator.Reset(index);
|
|
} else if (tagName != nsSchemaAtoms::sAnnotation_atom &&
|
|
tagName != nsSchemaAtoms::sRedefine_atom &&
|
|
tagName != nsSchemaAtoms::sNotation_atom) {
|
|
// if it is none of these, unexpected element.
|
|
nsAutoString elementName;
|
|
nsresult rc = aElement->GetTagName(elementName);
|
|
NS_ENSURE_SUCCESS(rc, rc);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unexpected element \"");
|
|
errorMsg.Append(elementName);
|
|
errorMsg.AppendLiteral("\" in <schema .../>");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema");
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
// We need to add this schema into the schema collection because resolving
|
|
// forward references may require resolving types with namespace prefixes,
|
|
// which could easily point back at this schema file.
|
|
mSchemas.Put(targetNamespace, schemaInst);
|
|
|
|
// Resolve all forward references
|
|
rv = schemaInst->Resolve(aErrorHandler);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
NS_ADDREF(*aResult = schemaInst);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
PRBool
|
|
ParseQualifiedName(nsIDOMElement* aContext,
|
|
const nsAString& aQualifiedName,
|
|
nsAString& aPrefix,
|
|
nsAString& aLocalName,
|
|
nsAString& aNamespaceURI)
|
|
{
|
|
const PRUnichar *pos, *begin, *end;
|
|
|
|
aQualifiedName.BeginReading(&begin, &end);
|
|
pos = begin;
|
|
|
|
while (pos < end && *pos != ':') {
|
|
++pos;
|
|
}
|
|
|
|
if (pos < end) {
|
|
aPrefix.Assign(Substring(begin, pos-begin));
|
|
aLocalName.Assign(Substring(++pos, end-pos));
|
|
}
|
|
else {
|
|
aLocalName.Assign(aQualifiedName);
|
|
}
|
|
|
|
nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(aContext));
|
|
|
|
return node->LookupNamespaceURI(aPrefix, aNamespaceURI);
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::GetNewOrUsedType(nsSchema* aSchema,
|
|
nsIDOMElement* aContext,
|
|
const nsAString& aTypeName,
|
|
nsISVSchemaType** 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.IsEmpty() && 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;
|
|
}
|
|
|
|
/**
|
|
* @param aErrorHandler Error handler (in).
|
|
* @param aSchema Schema in which is the element, not null (in).
|
|
* @param aElement DOM element <element .../>, not null (in).
|
|
* @param aSchemaElement Schema element from processing DOM element (out).
|
|
*/
|
|
nsresult
|
|
nsSchemaLoader::ProcessElement(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISVSchemaElement** aSchemaElement)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsISVSchemaElement> 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.IsEmpty()) {
|
|
nsSchemaElementRef* elementRef;
|
|
nsAutoString refNS;
|
|
|
|
// need to handle ns:type
|
|
rv = ParseNameAndNS(ref, aElement, ref, refNS);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
elementRef = new nsSchemaElementRef(aSchema, ref, refNS);
|
|
if (!elementRef) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
schemaElement = elementRef;
|
|
|
|
elementRef->SetMinOccurs(minOccurs);
|
|
elementRef->SetMaxOccurs(maxOccurs);
|
|
}
|
|
else {
|
|
nsAutoString value;
|
|
nsSchemaElement* elementInst;
|
|
const nsAString& empty = EmptyString();
|
|
|
|
rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("name"), value);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
nsresult rc = aElement->GetTagName(value);
|
|
NS_ENSURE_SUCCESS(rc, rc);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
|
|
errorMsg.AppendLiteral("attribute \"name\" of element \"");
|
|
errorMsg.Append(value);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
value.Trim(" \r\n\t");
|
|
elementInst = new nsSchemaElement(aSchema, value);
|
|
if (!elementInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
schemaElement = elementInst;
|
|
|
|
elementInst->SetMinOccurs(minOccurs);
|
|
elementInst->SetMaxOccurs(maxOccurs);
|
|
|
|
nsAutoString defaultValue, fixedValue;
|
|
rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("default"),
|
|
defaultValue);
|
|
if (NS_FAILED(rv)) {
|
|
nsresult rc = aElement->GetTagName(value);
|
|
NS_ENSURE_SUCCESS(rc, rc);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
|
|
errorMsg.AppendLiteral("attribute \"default\" of element \"");
|
|
errorMsg.Append(value);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("fixed"),
|
|
fixedValue);
|
|
if (NS_FAILED(rv)) {
|
|
nsresult rc = aElement->GetTagName(value);
|
|
NS_ENSURE_SUCCESS(rc, rc);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
|
|
errorMsg.AppendLiteral("attribute \"fixed\" of element \"");
|
|
errorMsg.Append(value);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
elementInst->SetConstraints(defaultValue, fixedValue);
|
|
|
|
rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("nillable"), value);
|
|
if (NS_FAILED(rv)) {
|
|
nsresult rc = aElement->GetTagName(value);
|
|
NS_ENSURE_SUCCESS(rc, rc);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
|
|
errorMsg.AppendLiteral("attribute \"nillable\" of element \"");
|
|
errorMsg.Append(value);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
value.Trim(" \r\n\t");
|
|
|
|
PRInt32 flags = 0;
|
|
if (value.EqualsLiteral("true"))
|
|
flags |= nsSchemaElement::NILLABLE;
|
|
|
|
rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("abstract"), value);
|
|
if (NS_FAILED(rv)) {
|
|
nsresult rc = aElement->GetTagName(value);
|
|
NS_ENSURE_SUCCESS(rc, rc);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
|
|
errorMsg.AppendLiteral("attribute \"abstract\" of element \"");
|
|
errorMsg.Append(value);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
value.Trim(" \r\n\t");
|
|
|
|
if (value.EqualsLiteral("true"))
|
|
flags |= nsSchemaElement::ABSTRACT;
|
|
|
|
nsCOMPtr<nsIDOMNode> parent;
|
|
rv = aElement->GetParentNode(getter_AddRefs(parent));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
parent->GetLocalName(value);
|
|
|
|
// Check if the schema element's targetNamespace applies to <element>.
|
|
// Note: If the <element> element information item has <schema> as its
|
|
// parent,then the actual value of the targetNamespace is that of the
|
|
// parent <schema> element information item, or absent if there is
|
|
// none. Otherwise if the <element> element information item has
|
|
// <schema> element as an ancestor then if "form" is present and its actual
|
|
// value is qualified, or if "form" is absent and the actual value of
|
|
// elementFormDefault on the <schema> ancestor is qualified, then the
|
|
// actual value of the targetNamespace [attribute] is that of the ancestor
|
|
// <schema> element information item, or absent if there is none.
|
|
if (value.EqualsLiteral("schema")) {
|
|
flags |= nsSchemaElement::FORM_QUALIFIED;
|
|
}
|
|
else {
|
|
rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("form"),
|
|
value);
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
|
|
errorMsg.AppendLiteral("attribute \"form\" of element \"");
|
|
errorMsg.Append(value);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
value.Trim(" \r\n\t");
|
|
if (value.IsEmpty()) {
|
|
if (aSchema->IsElementFormQualified()) {
|
|
flags |= nsSchemaElement::FORM_QUALIFIED;
|
|
}
|
|
else {
|
|
flags &= ~nsSchemaElement::FORM_QUALIFIED;
|
|
}
|
|
}
|
|
else if (value.EqualsLiteral("qualified")) {
|
|
flags |= nsSchemaElement::FORM_QUALIFIED;
|
|
}
|
|
else {
|
|
flags &= ~nsSchemaElement::FORM_QUALIFIED;
|
|
}
|
|
}
|
|
|
|
elementInst->SetFlags(flags);
|
|
|
|
nsCOMPtr<nsISVSchemaType> schemaType;
|
|
nsAutoString typeStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("type"), typeStr);
|
|
if (!typeStr.IsEmpty()) {
|
|
rv = GetNewOrUsedType(aSchema, aElement, typeStr,
|
|
getter_AddRefs(schemaType));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unknown type \"");
|
|
errorMsg.Append(typeStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
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<nsISVSchemaSimpleType> simpleType;
|
|
|
|
rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
|
|
getter_AddRefs(simpleType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
schemaType = simpleType;
|
|
break;
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sComplexType_atom) {
|
|
nsCOMPtr<nsISVSchemaComplexType> complexType;
|
|
|
|
rv = ProcessComplexType(aErrorHandler, 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)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, cannot find \'anyType\' ");
|
|
errorMsg.AppendLiteral("placeholder type in namespace \"");
|
|
errorMsg.Append(ns);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
rv = elementInst->SetType(schemaType);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
*aSchemaElement = schemaElement;
|
|
NS_ADDREF(*aSchemaElement);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
/**
|
|
* Handle <complexType ...>
|
|
*
|
|
* @param aErrorHandler Webservice error handler.
|
|
* @param aSchema Owning schema (in)
|
|
* @param aElement <complexType> element (in)
|
|
* @param aComplexType Schema complex type built from |aElement|
|
|
*/
|
|
nsresult
|
|
nsSchemaLoader::ProcessComplexType(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISVSchemaComplexType** aComplexType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsISVSchemaComplexType> 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.EqualsLiteral("true"));
|
|
if (!typeInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
complexType = typeInst;
|
|
|
|
rv = typeInst->Init();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
PRUint16 contentModel = nsISVSchemaComplexType::CONTENT_MODEL_EMPTY;
|
|
PRUint16 derivation = nsISVSchemaComplexType::DERIVATION_SELF_CONTAINED;
|
|
nsCOMPtr<nsISVSchemaType> baseType;
|
|
nsCOMPtr<nsISVSchemaModelGroup> modelGroup;
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sSimpleContent_atom) {
|
|
contentModel = nsISVSchemaComplexType::CONTENT_MODEL_SIMPLE;
|
|
|
|
rv = ProcessSimpleContent(aErrorHandler, aSchema, childElement, typeInst,
|
|
&derivation, getter_AddRefs(baseType));
|
|
break;
|
|
}
|
|
|
|
if (tagName == nsSchemaAtoms::sComplexContent_atom) {
|
|
rv = ProcessComplexContent(aErrorHandler, aSchema, childElement, typeInst,
|
|
&contentModel, &derivation,
|
|
getter_AddRefs(baseType));
|
|
break;
|
|
}
|
|
|
|
if (tagName == nsSchemaAtoms::sModelGroup_atom ||
|
|
tagName == nsSchemaAtoms::sAll_atom ||
|
|
tagName == nsSchemaAtoms::sChoice_atom ||
|
|
tagName == nsSchemaAtoms::sSequence_atom ||
|
|
tagName == nsSchemaAtoms::sAttribute_atom ||
|
|
tagName == nsSchemaAtoms::sAttributeGroup_atom ||
|
|
tagName == nsSchemaAtoms::sAnyAttribute_atom) {
|
|
rv = ProcessComplexTypeBody(aErrorHandler, aSchema,
|
|
aElement, typeInst, nsnull,
|
|
&contentModel);
|
|
break;
|
|
}
|
|
|
|
if (tagName == nsSchemaAtoms::sAnnotation_atom) {
|
|
// XXX: skipping for now
|
|
}
|
|
else {
|
|
// Unexpected schema element
|
|
nsAutoString elementName;
|
|
rv = aElement->GetTagName(elementName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = NS_ERROR_UNEXPECTED;
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unexpected element \"");
|
|
errorMsg.Append(elementName);
|
|
errorMsg.AppendLiteral("\" in <complexType />, should be <simpleContent .../>");
|
|
errorMsg.AppendLiteral(", <complexContent ../>, <annotation .../>");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
nsAutoString mixed;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("mixed"), mixed);
|
|
if (mixed.EqualsLiteral("true")) {
|
|
contentModel = nsISVSchemaComplexType::CONTENT_MODEL_MIXED;
|
|
}
|
|
|
|
typeInst->SetContentModel(contentModel);
|
|
typeInst->SetDerivation(derivation, baseType);
|
|
|
|
*aComplexType = complexType;
|
|
NS_ADDREF(*aComplexType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsSchemaLoader::ConstructArrayName(nsISVSchemaType* aType,
|
|
nsAString& aName)
|
|
{
|
|
nsAutoString typeName;
|
|
|
|
aType->GetName(typeName);
|
|
aName.AssignLiteral("ArrayOf");
|
|
aName.Append(typeName);
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ParseDimensions(nsSchema* aSchema,
|
|
nsIDOMElement* aAttrElement,
|
|
const nsAString& aStr,
|
|
nsISVSchemaType* aBaseType,
|
|
nsISVSchemaType** aArrayType,
|
|
PRUint32* aDimension)
|
|
{
|
|
const PRUnichar *iter, *done_reading;
|
|
aStr.BeginReading(&iter, &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<nsISVSchemaType> myArrayType;
|
|
PRUint32 myDimension;
|
|
|
|
nsresult rv = ParseDimensions(aSchema, aAttrElement,
|
|
nsDependentSubstring(iter, done_reading-iter),
|
|
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<nsISVSchemaComplexType> complexType = typeInst;
|
|
|
|
rv = typeInst->Init();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsISVSchemaType> 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(nsISVSchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY);
|
|
typeInst->SetDerivation(nsISVSchemaComplexType::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 nsAString& aStr,
|
|
nsISVSchemaType** aType,
|
|
PRUint32* aDimension)
|
|
{
|
|
PRInt32 offset;
|
|
|
|
offset = aStr.FindChar(PRUnichar('['));
|
|
if (offset == -1) {
|
|
return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
|
|
}
|
|
nsDependentSubstring typeStr(aStr, 0, offset);
|
|
|
|
nsCOMPtr<nsISVSchemaType> 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(nsISVSchemaErrorHandler* aErrorHandler,
|
|
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 = nsISVSchemaComplexType::CONTENT_MODEL_EMPTY;
|
|
|
|
nsCOMPtr<nsISVSchemaModelGroup> 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)) {
|
|
|
|
if (modelGroup) {
|
|
// We shouldn't already have a model group
|
|
nsAutoString elementName;
|
|
nsresult rv = childElement->GetTagName(elementName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, must have ");
|
|
errorMsg.AppendLiteral("model group in <complexType .../>, ");
|
|
errorMsg.AppendLiteral("unexpected element \"");
|
|
errorMsg.Append(elementName);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_STRUCTURE, errorMsg);
|
|
|
|
return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
|
|
}
|
|
|
|
rv = ProcessModelGroup(aErrorHandler, aSchema,
|
|
childElement, tagName,
|
|
aSequence, getter_AddRefs(modelGroup));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
PRUint32 particleCount;
|
|
modelGroup->GetParticleCount(&particleCount);
|
|
if (particleCount) {
|
|
*aContentModel = nsISVSchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY;
|
|
}
|
|
else {
|
|
PRUint16 compositor;
|
|
modelGroup->GetCompositor(&compositor);
|
|
|
|
PRUint32 minOccurs;
|
|
modelGroup->GetMinOccurs(&minOccurs);
|
|
|
|
if ((compositor == nsISVSchemaModelGroup::COMPOSITOR_CHOICE) &&
|
|
(minOccurs > 0)) {
|
|
*aContentModel = nsISVSchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY;
|
|
}
|
|
}
|
|
|
|
if (aSequence) {
|
|
// Check if we were collapsed
|
|
if (modelGroup.get() != static_cast<nsISVSchemaModelGroup *>(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<nsISVSchemaAttributeComponent> attribute;
|
|
|
|
rv = ProcessAttributeComponent(aErrorHandler, aSchema,
|
|
childElement, tagName,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->AddAttribute(attribute);
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString elementName;
|
|
nsAutoString attributeName;
|
|
nsresult rc = childElement->GetTagName(elementName);
|
|
NS_ENSURE_SUCCESS(rc, rc);
|
|
|
|
rc = attribute->GetName(attributeName);
|
|
NS_ENSURE_SUCCESS(rc, rc);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, cannot process attribute \"");
|
|
errorMsg.Append(attributeName);
|
|
errorMsg.AppendLiteral("\" of element \"");
|
|
errorMsg.Append(elementName);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
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<nsISVSchemaType> arraySchemaType;
|
|
PRUint32 arrayDimension;
|
|
rv = ParseArrayType(aSchema,
|
|
childElement,
|
|
arrayType,
|
|
getter_AddRefs(arraySchemaType),
|
|
&arrayDimension);
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, ");
|
|
errorMsg.AppendLiteral("cannot process array type \"");
|
|
errorMsg.Append(arrayType);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->SetArrayInfo(arraySchemaType, arrayDimension);
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, cannot set ");
|
|
errorMsg.AppendLiteral("array information for array type \"");
|
|
errorMsg.Append(arrayType);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleContent(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsSchemaComplexType* aComplexType,
|
|
PRUint16* aDerivation,
|
|
nsISVSchemaType** aBaseType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsISVSchemaType> baseType;
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
// A simpleContent element must have children
|
|
if (!iterator.HasChildNodes()) {
|
|
nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing schema, "));
|
|
errorMsg.AppendLiteral("<simpleContent .../> invalid structure, should contains ");
|
|
errorMsg.AppendLiteral("<restriction .../> or <extension .../>");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_STRUCTURE, errorMsg);
|
|
|
|
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.IsEmpty()) {
|
|
nsAutoString elementName;
|
|
rv = childElement->GetTagName(elementName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, \"");
|
|
errorMsg.Append(elementName);
|
|
errorMsg.AppendLiteral("\" must have a \"base\" attribute in order ");
|
|
errorMsg.AppendLiteral("to specify base type");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_MISSING_TYPE, errorMsg);
|
|
|
|
return NS_ERROR_SCHEMA_MISSING_TYPE;
|
|
}
|
|
|
|
rv = GetNewOrUsedType(aSchema, childElement, baseStr,
|
|
getter_AddRefs(baseType));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unknown base type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsISVSchemaSimpleType> simpleBaseType;
|
|
if (tagName == nsSchemaAtoms::sRestriction_atom) {
|
|
*aDerivation = nsISVSchemaComplexType::DERIVATION_RESTRICTION_SIMPLE;
|
|
rv = ProcessSimpleContentRestriction(aErrorHandler, aSchema, childElement,
|
|
aComplexType, baseType,
|
|
getter_AddRefs(simpleBaseType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
*aDerivation = nsISVSchemaComplexType::DERIVATION_EXTENSION_SIMPLE;
|
|
|
|
nsCOMPtr<nsISVSchemaComplexType> 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<nsISVSchemaAttributeComponent> attribute;
|
|
|
|
rv = complexBaseType->GetAttributeByIndex(attrIndex,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
|
|
errorMsg.AppendLiteral("attributes from base type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->AddAttribute(attribute);
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
|
|
errorMsg.AppendLiteral("attributes from base type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
rv = ProcessSimpleContentExtension(aErrorHandler, 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(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsSchemaComplexType* aComplexType,
|
|
nsISVSchemaType* aBaseType,
|
|
nsISVSchemaSimpleType** aSimpleBaseType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
nsSchemaRestrictionType* restrictionInst;
|
|
nsCOMPtr<nsISVSchemaSimpleType> simpleBase;
|
|
|
|
restrictionInst = new nsSchemaRestrictionType(aSchema, EmptyString());
|
|
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<nsISVSchemaComplexType> complexBase = do_QueryInterface(aBaseType);
|
|
if (!complexBase) {
|
|
// if base type is a place holder, this is ok
|
|
PRUint16 schemaType;
|
|
rv = aBaseType->GetSchemaType(&schemaType);
|
|
|
|
if (NS_SUCCEEDED(rv) && schemaType == nsISVSchemaType::SCHEMA_TYPE_PLACEHOLDER) {
|
|
simpleBase = do_QueryInterface(aBaseType);
|
|
} else {
|
|
nsAutoString baseStr;
|
|
rv = aBaseType->GetName(baseStr);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, base type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\" of restriction must be a complex type ");
|
|
errorMsg.AppendLiteral("which itself must be based on a simple type");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
|
|
|
|
return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
|
|
}
|
|
} else {
|
|
nsCOMPtr<nsISVSchemaSimpleType> parentSimpleBase;
|
|
complexBase->GetSimpleBaseType(getter_AddRefs(parentSimpleBase));
|
|
|
|
if (parentSimpleBase) {
|
|
rv = restrictionInst->SetBaseType(parentSimpleBase);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
}
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName == nsSchemaAtoms::sSimpleType_atom) {
|
|
nsCOMPtr<nsISVSchemaSimpleType> simpleType;
|
|
|
|
rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
|
|
getter_AddRefs(simpleType));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = restrictionInst->SetBaseType(simpleType);
|
|
NS_ENSURE_SUCCESS(rv, 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<nsISVSchemaFacet> facet;
|
|
|
|
rv = ProcessFacet(aErrorHandler, aSchema, childElement,
|
|
tagName, getter_AddRefs(facet));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = restrictionInst->AddFacet(facet);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
else if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
|
|
(tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
|
|
(tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
|
|
nsCOMPtr<nsISVSchemaAttributeComponent> attribute;
|
|
|
|
rv = ProcessAttributeComponent(aErrorHandler, aSchema,
|
|
childElement, tagName,
|
|
getter_AddRefs(attribute));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aComplexType->AddAttribute(attribute);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
}
|
|
|
|
*aSimpleBaseType = simpleBase;
|
|
NS_IF_ADDREF(*aSimpleBaseType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleContentExtension(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsSchemaComplexType* aComplexType,
|
|
nsISVSchemaType* aBaseType,
|
|
nsISVSchemaSimpleType** 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<nsISVSchemaComplexType> complexBase = do_QueryInterface(aBaseType);
|
|
if (complexBase) {
|
|
complexBase->GetSimpleBaseType(aSimpleBaseType);
|
|
}
|
|
else {
|
|
aBaseType->QueryInterface(NS_GET_IID(nsISVSchemaSimpleType),
|
|
(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<nsISVSchemaAttributeComponent> attribute;
|
|
|
|
rv = ProcessAttributeComponent(aErrorHandler, 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(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsSchemaComplexType* aComplexType,
|
|
PRUint16* aContentModel,
|
|
PRUint16* aDerivation,
|
|
nsISVSchemaType** aBaseType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsISVSchemaType> baseType;
|
|
nsChildElementIterator iterator(aElement,
|
|
kSchemaNamespaces,
|
|
kSchemaNamespacesLength);
|
|
nsCOMPtr<nsIDOMElement> childElement;
|
|
nsCOMPtr<nsIAtom> tagName;
|
|
|
|
// A complexContent element must have children
|
|
if (!iterator.HasChildNodes()) {
|
|
nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing schema, "));
|
|
errorMsg.AppendLiteral("<complexContent .../> must contains ");
|
|
errorMsg.AppendLiteral("<restriction .../> or <extension .../>");
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_STRUCTURE, errorMsg);
|
|
|
|
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.IsEmpty()) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, ");
|
|
|
|
if (tagName == nsSchemaAtoms::sRestriction_atom) {
|
|
errorMsg.AppendLiteral("restriction");
|
|
}
|
|
else {
|
|
errorMsg.AppendLiteral("extension");
|
|
}
|
|
|
|
errorMsg.AppendLiteral(" must have a \"base\" attribute in order to ");
|
|
errorMsg.AppendLiteral("specify base type");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_MISSING_TYPE, errorMsg);
|
|
|
|
return NS_ERROR_SCHEMA_MISSING_TYPE;
|
|
}
|
|
|
|
rv = GetNewOrUsedType(aSchema, childElement, baseStr,
|
|
getter_AddRefs(baseType));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unknown base type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsISVSchemaComplexType> complexBaseType(do_QueryInterface(baseType));
|
|
|
|
if (tagName == nsSchemaAtoms::sRestriction_atom) {
|
|
*aDerivation = nsISVSchemaComplexType::DERIVATION_RESTRICTION_COMPLEX;
|
|
rv = ProcessComplexTypeBody(aErrorHandler, aSchema, childElement,
|
|
aComplexType, nsnull, aContentModel);
|
|
}
|
|
else {
|
|
*aDerivation = nsISVSchemaComplexType::DERIVATION_EXTENSION_COMPLEX;
|
|
|
|
nsCOMPtr<nsISVSchemaModelGroup> sequence;
|
|
nsSchemaModelGroup* sequenceInst = nsnull;
|
|
if (complexBaseType) {
|
|
// XXX Should really be cloning
|
|
nsCOMPtr<nsISVSchemaModelGroup> baseGroup;
|
|
rv = complexBaseType->GetModelGroup(getter_AddRefs(baseGroup));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, extension for type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\" does not contains any model group");
|
|
errorMsg.AppendLiteral("such as <all>, <choice>, <sequence>, or <group>");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
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, EmptyString());
|
|
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 == nsISVSchemaModelGroup::COMPOSITOR_SEQUENCE) &&
|
|
(minOccurs == 1) && (maxOccurs == 1)) {
|
|
PRUint32 pIndex, pCount;
|
|
baseGroup->GetParticleCount(&pCount);
|
|
for (pIndex = 0; pIndex < pCount; pIndex++) {
|
|
nsCOMPtr<nsISVSchemaParticle> particle;
|
|
|
|
rv = baseGroup->GetParticle(pIndex, getter_AddRefs(particle));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, failure ");
|
|
errorMsg.AppendLiteral("processing model group for extension ");
|
|
errorMsg.AppendLiteral("of type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
rv = sequenceInst->AddParticle(particle);
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, failure ");
|
|
errorMsg.AppendLiteral("processing model group for extension ");
|
|
errorMsg.AppendLiteral("of type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
sequenceInst->AddParticle(baseGroup);
|
|
}
|
|
|
|
aComplexType->SetModelGroup(sequence);
|
|
}
|
|
}
|
|
|
|
PRUint16 explicitContent;
|
|
rv = ProcessComplexTypeBody(aErrorHandler, 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 == nsISVSchemaComplexType::CONTENT_MODEL_EMPTY) &&
|
|
complexBaseType) {
|
|
complexBaseType->GetContentModel(aContentModel);
|
|
}
|
|
else {
|
|
*aContentModel = explicitContent;
|
|
}
|
|
}
|
|
|
|
// Copy over the attributes from the base type
|
|
// XXX Should really be cloning
|
|
if (complexBaseType) {
|
|
PRUint32 attrIndex, attrCount;
|
|
complexBaseType->GetAttributeCount(&attrCount);
|
|
|
|
for (attrIndex = 0; attrIndex < attrCount; attrIndex++) {
|
|
nsCOMPtr<nsISVSchemaAttributeComponent> attribute;
|
|
|
|
rv = complexBaseType->GetAttributeByIndex(attrIndex,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
|
|
errorMsg.AppendLiteral("attributes from base type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
rv = aComplexType->AddAttribute(attribute);
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
|
|
errorMsg.AppendLiteral("attributes from base type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
nsAutoString mixed;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("mixed"), mixed);
|
|
if (mixed.EqualsLiteral("true")) {
|
|
*aContentModel = nsISVSchemaComplexType::CONTENT_MODEL_MIXED;
|
|
}
|
|
|
|
*aBaseType = baseType;
|
|
NS_IF_ADDREF(*aBaseType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleType(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISVSchemaSimpleType** 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(aErrorHandler, aSchema, childElement,
|
|
name, aSimpleType);
|
|
break;
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sList_atom) {
|
|
rv = ProcessSimpleTypeList(aErrorHandler, aSchema, childElement,
|
|
name, aSimpleType);
|
|
break;
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sUnion_atom) {
|
|
rv = ProcessSimpleTypeUnion(aErrorHandler, aSchema, childElement,
|
|
name, aSimpleType);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleTypeRestriction(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
const nsAString& aName,
|
|
nsISVSchemaSimpleType** aSimpleType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsSchemaRestrictionType* restrictionInst;
|
|
nsCOMPtr<nsISVSchemaSimpleType> restriction;
|
|
|
|
restrictionInst = new nsSchemaRestrictionType(aSchema, aName);
|
|
if (!restrictionInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
restriction = restrictionInst;
|
|
|
|
nsCOMPtr<nsISVSchemaType> baseType;
|
|
nsAutoString baseStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
|
|
if (!baseStr.IsEmpty()) {
|
|
rv = GetNewOrUsedType(aSchema, aElement, baseStr,
|
|
getter_AddRefs(baseType));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unknown base type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsISVSchemaSimpleType> simpleBase(do_QueryInterface(baseType));
|
|
if (!simpleBase) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, base type \"");
|
|
errorMsg.Append(baseStr);
|
|
errorMsg.AppendLiteral("\" should be a simple type");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
|
|
|
|
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<nsISVSchemaSimpleType> simpleType;
|
|
|
|
rv = ProcessSimpleType(aErrorHandler, 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<nsISVSchemaFacet> facet;
|
|
|
|
rv = ProcessFacet(aErrorHandler, 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(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
const nsAString& aName,
|
|
nsISVSchemaSimpleType** aSimpleType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsSchemaListType* listInst;
|
|
nsCOMPtr<nsISVSchemaSimpleType> 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<nsISVSchemaSimpleType> itemType;
|
|
if (!itemTypeStr.IsEmpty()) {
|
|
nsCOMPtr<nsISVSchemaType> type;
|
|
rv = GetNewOrUsedType(aSchema, aElement, itemTypeStr,
|
|
getter_AddRefs(type));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unknown item type \"");
|
|
errorMsg.Append(itemTypeStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
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(aErrorHandler, aSchema, childElement,
|
|
getter_AddRefs(itemType));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!itemType) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, no item type ");
|
|
errorMsg.AppendLiteral("for simple type \"");
|
|
errorMsg.Append(aName);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_MISSING_TYPE, errorMsg);
|
|
|
|
return NS_ERROR_SCHEMA_MISSING_TYPE;
|
|
}
|
|
listInst->SetListType(itemType);
|
|
|
|
*aSimpleType = list;
|
|
NS_ADDREF(*aSimpleType);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessSimpleTypeUnion(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
const nsAString& aName,
|
|
nsISVSchemaSimpleType** aSimpleType)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsSchemaUnionType* unionInst;
|
|
nsCOMPtr<nsISVSchemaSimpleType> unionType;
|
|
|
|
unionInst = new nsSchemaUnionType(aSchema, aName);
|
|
if (!unionInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
unionType = unionInst;
|
|
|
|
nsCOMPtr<nsISVSchemaSimpleType> memberType;
|
|
nsAutoString memberTypes;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("memberTypes"), memberTypes);
|
|
if (!memberTypes.IsEmpty()) {
|
|
const PRUnichar *begin = nsnull, *end, *tokenEnd;
|
|
|
|
memberTypes.BeginReading(&tokenEnd, &end);
|
|
|
|
while (tokenEnd != end) {
|
|
nsAutoString typeStr;
|
|
begin = tokenEnd;
|
|
while (tokenEnd < end && *tokenEnd != PRUnichar(' '))
|
|
++tokenEnd;
|
|
if (tokenEnd < end) {
|
|
typeStr.Assign(Substring(begin, tokenEnd-begin));
|
|
++tokenEnd;
|
|
}
|
|
else {
|
|
typeStr.Assign(Substring(begin, end-begin));
|
|
}
|
|
|
|
nsCOMPtr<nsISVSchemaType> type;
|
|
rv = GetNewOrUsedType(aSchema, aElement, typeStr,
|
|
getter_AddRefs(type));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unknown type \"");
|
|
errorMsg.Append(typeStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
memberType = do_QueryInterface(type);
|
|
if (!memberType) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, invalid member type \"");
|
|
errorMsg.Append(typeStr);
|
|
errorMsg.AppendLiteral("\" for union about simple type \"");
|
|
errorMsg.Append(aName);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
|
|
|
|
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(aErrorHandler, 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(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsIAtom* aTagName,
|
|
nsSchemaModelGroup* aParentSequence,
|
|
nsISVSchemaModelGroup** aModelGroup)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsISVSchemaModelGroup> modelGroup;
|
|
PRUint32 minOccurs, maxOccurs;
|
|
GetMinAndMax(aElement, &minOccurs, &maxOccurs);
|
|
|
|
// Check for a ref attribute
|
|
nsAutoString ref, refNS;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
|
|
|
|
if ((aTagName == nsSchemaAtoms::sModelGroup_atom) &&
|
|
!ref.IsEmpty()) {
|
|
|
|
rv = ParseNameAndNS(ref, aElement, ref, refNS);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsSchemaModelGroupRef* modelGroupRef = new nsSchemaModelGroupRef(aSchema,
|
|
ref,
|
|
refNS);
|
|
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(nsISVSchemaModelGroup::COMPOSITOR_ALL);
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sChoice_atom) {
|
|
modelGroupInst->SetCompositor(nsISVSchemaModelGroup::COMPOSITOR_CHOICE);
|
|
}
|
|
else if (tagName == nsSchemaAtoms::sSequence_atom) {
|
|
modelGroupInst->SetCompositor(nsISVSchemaModelGroup::COMPOSITOR_SEQUENCE);
|
|
}
|
|
}
|
|
|
|
while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
|
|
getter_AddRefs(tagName))) &&
|
|
childElement) {
|
|
if (tagName != nsSchemaAtoms::sAnnotation_atom) {
|
|
nsCOMPtr<nsISVSchemaParticle> particle;
|
|
|
|
rv = ProcessParticle(aErrorHandler, 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(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsIAtom* aTagName,
|
|
nsISVSchemaParticle** aParticle)
|
|
{
|
|
nsresult rv;
|
|
|
|
if (aTagName == nsSchemaAtoms::sElement_atom) {
|
|
nsCOMPtr<nsISVSchemaElement> element;
|
|
|
|
rv = ProcessElement(aErrorHandler, 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<nsISVSchemaModelGroup> modelGroup;
|
|
|
|
rv = ProcessModelGroup(aErrorHandler, 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<nsISVSchemaParticle> 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(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsIAtom* aTagName,
|
|
nsISVSchemaAttributeComponent** aAttribute)
|
|
{
|
|
nsresult rv;
|
|
|
|
if (aTagName == nsSchemaAtoms::sAttribute_atom) {
|
|
nsCOMPtr<nsISVSchemaAttribute> attribute;
|
|
|
|
rv = ProcessAttribute(aErrorHandler, aSchema, aElement,
|
|
getter_AddRefs(attribute));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
*aAttribute = attribute;
|
|
NS_IF_ADDREF(*aAttribute);
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sAttributeGroup_atom) {
|
|
nsCOMPtr<nsISVSchemaAttributeGroup> attributeGroup;
|
|
|
|
rv = ProcessAttributeGroup(aErrorHandler, aSchema, aElement,
|
|
getter_AddRefs(attributeGroup));
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
*aAttribute = attributeGroup;
|
|
NS_IF_ADDREF(*aAttribute);
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sAnyAttribute_atom) {
|
|
nsCOMPtr<nsISVSchemaAttributeComponent> 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(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISVSchemaAttribute** aAttribute)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsISVSchemaAttribute> attribute;
|
|
|
|
nsAutoString defaultValue, fixedValue, formValue;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("default"), defaultValue);
|
|
aElement->GetAttribute(NS_LITERAL_STRING("fixed"), fixedValue);
|
|
aElement->GetAttribute(NS_LITERAL_STRING("form"), formValue);
|
|
|
|
PRUint16 use;
|
|
GetUse(aElement, &use);
|
|
|
|
nsAutoString ref, refNS;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
|
|
if (!ref.IsEmpty()) {
|
|
rv = ParseNameAndNS(ref, aElement, ref, refNS);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsSchemaAttributeRef* attributeRef = new nsSchemaAttributeRef(aSchema,
|
|
ref, refNS);
|
|
if (!attributeRef) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
attribute = attributeRef;
|
|
|
|
attributeRef->SetConstraints(defaultValue, fixedValue);
|
|
attributeRef->SetUse(use);
|
|
|
|
// set the qualified form
|
|
if (formValue.EqualsLiteral("qualified")) {
|
|
attributeRef->SetAttributeFormQualified(PR_TRUE);
|
|
}
|
|
else if (formValue.EqualsLiteral("unqualified")) {
|
|
attributeRef->SetAttributeFormQualified(PR_FALSE);
|
|
}
|
|
else {
|
|
// get default
|
|
PRBool defaultvalue = aSchema->IsAttributeFormDefaultQualified();
|
|
attributeRef->SetAttributeFormQualified(defaultvalue);
|
|
}
|
|
}
|
|
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);
|
|
|
|
// set the qualified form
|
|
if (formValue.EqualsLiteral("qualified")) {
|
|
attributeInst->SetAttributeFormQualified(PR_TRUE);
|
|
}
|
|
else if (formValue.EqualsLiteral("unqualified")) {
|
|
attributeInst->SetAttributeFormQualified(PR_FALSE);
|
|
}
|
|
else {
|
|
// get default
|
|
PRBool defaultvalue = aSchema->IsAttributeFormDefaultQualified();
|
|
attributeInst->SetAttributeFormQualified(defaultvalue);
|
|
}
|
|
|
|
nsCOMPtr<nsISVSchemaSimpleType> 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(aErrorHandler, 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.IsEmpty()) {
|
|
nsCOMPtr<nsISVSchemaType> schemaType;
|
|
rv = GetNewOrUsedType(aSchema, aElement, typeStr,
|
|
getter_AddRefs(schemaType));
|
|
if (NS_FAILED(rv)) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unknown type \"");
|
|
errorMsg.Append(typeStr);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
simpleType = do_QueryInterface(schemaType);
|
|
if (!simpleType) {
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, invalid type \"");
|
|
errorMsg.Append(typeStr);
|
|
errorMsg.AppendLiteral("\" for attribute \"");
|
|
errorMsg.Append(name);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
|
|
|
|
return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
|
|
}
|
|
}
|
|
}
|
|
|
|
attributeInst->SetType(simpleType);
|
|
}
|
|
|
|
*aAttribute = attribute;
|
|
NS_ADDREF(*aAttribute);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ProcessAttributeGroup(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsISVSchemaAttributeGroup** aAttributeGroup)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsISVSchemaAttributeGroup> attributeGroup;
|
|
|
|
nsAutoString ref, refNS;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
|
|
|
|
if (!ref.IsEmpty()) {
|
|
// need to handle ns:type
|
|
rv = ParseNameAndNS(ref, aElement, ref, refNS);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsSchemaAttributeGroupRef* attrRef = new nsSchemaAttributeGroupRef(aSchema,
|
|
ref,
|
|
refNS);
|
|
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;
|
|
|
|
rv = attrInst->Init();
|
|
NS_ENSURE_SUCCESS(rv, 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::sAttribute_atom) ||
|
|
(tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
|
|
(tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
|
|
nsCOMPtr<nsISVSchemaAttributeComponent> attribute;
|
|
|
|
rv = ProcessAttributeComponent(aErrorHandler, 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(nsISVSchemaErrorHandler* aErrorHandler,
|
|
nsSchema* aSchema,
|
|
nsIDOMElement* aElement,
|
|
nsIAtom* aTagName,
|
|
nsISVSchemaFacet** aFacet)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsISVSchemaFacet> facet;
|
|
nsSchemaFacet* facetInst = new nsSchemaFacet(aSchema);
|
|
if (!facetInst) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
facet = facetInst;
|
|
|
|
PRUint16 facetType;
|
|
if (aTagName == nsSchemaAtoms::sLength_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_LENGTH;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMinLength_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_MINLENGTH;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMaxLength_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_MAXLENGTH;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sPattern_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_PATTERN;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sEnumeration_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_ENUMERATION;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sWhiteSpace_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_WHITESPACE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMaxInclusive_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_MAXINCLUSIVE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMinInclusive_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_MININCLUSIVE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMaxExclusive_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_MAXEXCLUSIVE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sMinExclusive_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_MINEXCLUSIVE;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sTotalDigits_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_TOTALDIGITS;
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sFractionDigits_atom) {
|
|
facetType = nsISVSchemaFacet::FACET_TYPE_FRACTIONDIGITS;
|
|
}
|
|
else {
|
|
nsAutoString elementName;
|
|
rv = aElement->GetTagName(elementName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, unknown type of facet \"");
|
|
errorMsg.Append(elementName);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_UNEXPECTED, errorMsg);
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
facetInst->SetFacetType(facetType);
|
|
|
|
nsAutoString valueStr;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("value"), valueStr);
|
|
if (valueStr.IsEmpty()) {
|
|
nsAutoString elementName;
|
|
rv = aElement->GetTagName(elementName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, invalid empty value ");
|
|
errorMsg.AppendLiteral("for facet \"");
|
|
errorMsg.Append(elementName);
|
|
errorMsg.AppendLiteral("\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
|
|
|
|
return rv;
|
|
}
|
|
|
|
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))) {
|
|
nsAutoString elementName;
|
|
rv = aElement->GetTagName(elementName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, invalid value for facet \"");
|
|
errorMsg.Append(elementName);
|
|
errorMsg.AppendLiteral("\", <=0");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_FACET_VALUE_ERROR, errorMsg);
|
|
|
|
return NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
|
|
}
|
|
|
|
facetInst->SetUintValue((PRUint32)intVal);
|
|
}
|
|
else if (aTagName == nsSchemaAtoms::sWhiteSpace_atom) {
|
|
PRUint16 whiteSpaceVal;
|
|
if (valueStr.EqualsLiteral("collapse")) {
|
|
whiteSpaceVal = nsSchemaFacet::WHITESPACE_COLLAPSE;
|
|
}
|
|
else if (valueStr.EqualsLiteral("preserve")) {
|
|
whiteSpaceVal = nsSchemaFacet::WHITESPACE_PRESERVE;
|
|
}
|
|
else if (valueStr.EqualsLiteral("replace")) {
|
|
whiteSpaceVal = nsSchemaFacet::WHITESPACE_REPLACE;
|
|
}
|
|
else {
|
|
nsAutoString elementName;
|
|
rv = aElement->GetTagName(elementName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString errorMsg;
|
|
errorMsg.AppendLiteral("Failure processing schema, invalid value for facet \"");
|
|
errorMsg.Append(elementName);
|
|
errorMsg.AppendLiteral("\", should be \"collapse\", \"preserve\" or \"replace\"");
|
|
|
|
NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_FACET_VALUE_ERROR, errorMsg);
|
|
|
|
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.EqualsLiteral("true"));
|
|
|
|
*aFacet = facet;
|
|
NS_ADDREF(*aFacet);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsSchemaLoader::GetUse(nsIDOMElement* aElement,
|
|
PRUint16* aUse)
|
|
{
|
|
*aUse = nsISVSchemaAttribute::USE_OPTIONAL;
|
|
|
|
nsAutoString use;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("use"), use);
|
|
|
|
if (use.EqualsLiteral("prohibited")) {
|
|
*aUse = nsISVSchemaAttribute::USE_PROHIBITED;
|
|
}
|
|
else if (use.EqualsLiteral("required")) {
|
|
*aUse = nsISVSchemaAttribute::USE_REQUIRED;
|
|
}
|
|
}
|
|
|
|
void
|
|
nsSchemaLoader::GetProcess(nsIDOMElement* aElement,
|
|
PRUint16* aProcess)
|
|
{
|
|
*aProcess = nsISVSchemaAnyParticle::PROCESS_STRICT;
|
|
|
|
nsAutoString process;
|
|
aElement->GetAttribute(NS_LITERAL_STRING("process"), process);
|
|
|
|
if (process.EqualsLiteral("lax")) {
|
|
*aProcess = nsISVSchemaAnyParticle::PROCESS_LAX;
|
|
}
|
|
else if (process.EqualsLiteral("skip")) {
|
|
*aProcess = nsISVSchemaAnyParticle::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);
|
|
|
|
nsresult rv;
|
|
if (!minStr.IsEmpty()) {
|
|
PRInt32 minVal = minStr.ToInteger(&rv);
|
|
if (NS_SUCCEEDED(rv) && (minVal >= 0)) {
|
|
*aMinOccurs = (PRUint32)minVal;
|
|
}
|
|
}
|
|
|
|
if (!maxStr.IsEmpty()) {
|
|
if (maxStr.EqualsLiteral("unbounded")) {
|
|
*aMaxOccurs = nsISVSchemaParticle::OCCURRENCE_UNBOUNDED;
|
|
}
|
|
else {
|
|
PRInt32 maxVal = maxStr.ToInteger(&rv);
|
|
if (NS_SUCCEEDED(rv) && (maxVal >= 0)) {
|
|
*aMaxOccurs = (PRUint32)maxVal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::ParseNameAndNS(const nsAString& aName, nsIDOMElement* aElement,
|
|
nsAString& aTypeName, nsAString& aTypeNS)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIParserService> parserService =
|
|
do_GetService("@mozilla.org/parser/parser-service;1", &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
const nsString& qName = PromiseFlatString(aName);
|
|
const PRUnichar *colon;
|
|
rv = parserService->CheckQName(qName, PR_TRUE, &colon);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (colon) {
|
|
const PRUnichar* end = qName.EndReading();
|
|
|
|
nsAutoString schemaTypePrefix;
|
|
schemaTypePrefix.Assign(Substring(qName.get(), colon));
|
|
aTypeName.Assign(Substring(colon + 1, end));
|
|
|
|
nsCOMPtr<nsIDOM3Node> domNode3 = do_QueryInterface(aElement);
|
|
NS_ENSURE_STATE(domNode3);
|
|
|
|
// get the namespace url from the prefix
|
|
rv = domNode3->LookupNamespaceURI(schemaTypePrefix, aTypeNS);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsSchemaLoader::GetDocumentFromURI(const nsAString& aUri,
|
|
nsIDOMDocument** aDocument)
|
|
{
|
|
*aDocument = nsnull;
|
|
|
|
nsCOMPtr<nsIURI> resolvedURI;
|
|
nsresult rv = GetResolvedURI(aUri, "load", getter_AddRefs(resolvedURI));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIXMLHttpRequest> request =
|
|
do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCAutoString spec;
|
|
resolvedURI->GetSpec(spec);
|
|
|
|
const nsAString& empty = EmptyString();
|
|
rv = request->OpenRequest(NS_LITERAL_CSTRING("GET"), spec, PR_FALSE, empty,
|
|
empty);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Force the mimetype of the returned stream to be xml.
|
|
rv = request->OverrideMimeType(NS_LITERAL_CSTRING("application/xml"));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = request->Send(nsnull);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIDOMDocument> document;
|
|
rv = request->GetResponseXML(getter_AddRefs(document));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (document) {
|
|
document.swap(*aDocument);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|