if (NS_FAILED(rc)) return rc;
NS_ENSURE_SUCCESS(rc, rc);
static nsresult EncodeStructParticle(nsISOAPEncoding* aEncoding, nsIPropertyBag* aPropertyBag,                                nsISchemaParticle* aParticle,                                nsISOAPAttachments * aAttachments, nsIDOMElement* aDestination){  nsresult rc;  if (aParticle) {    PRUint32 minOccurs;    rc = aParticle->GetMinOccurs(&minOccurs);    if (NS_FAILED(rc))      return rc;    PRUint32 maxOccurs;    rc = aParticle->GetMaxOccurs(&maxOccurs);    if (NS_FAILED(rc))      return rc;    PRUint16 particleType;    rc = aParticle->GetParticleType(&particleType);    if (NS_FAILED(rc))      return rc;    switch(particleType) {      case nsISchemaParticle::PARTICLE_TYPE_ELEMENT: {        if (maxOccurs > 1) {  //  Todo: Try to make this thing work as an array?          return NS_ERROR_NOT_AVAILABLE; //  For now, we just try something else if we can (recoverable)        }        nsCOMPtr<nsISchemaElement> element = do_QueryInterface(aParticle);        nsAutoString name;        rc = element->GetTargetNamespace(name);        if (NS_FAILED(rc))          return rc;        if (!name.IsEmpty()) {          rc = NS_ERROR_NOT_AVAILABLE; //  No known way to use namespace qualification in struct        }        else {          rc = element->GetName(name);          if (NS_FAILED(rc))            return rc;          rc = element->GetName(name);          if (NS_FAILED(rc))            return rc;          nsCOMPtr<nsISchemaType> type;          rc = element->GetType(getter_AddRefs(type));          if (NS_FAILED(rc))            return rc;          nsCOMPtr<nsIVariant> value;          rc = aPropertyBag->GetProperty(name, getter_AddRefs(value));          if (NS_SUCCEEDED(rc)) {            nsCOMPtr<nsIDOMElement> dummy;            rc = aEncoding->Encode(value, gSOAPStrings->kEmpty, name, type, aAttachments, aDestination, getter_AddRefs(dummy));            if (NS_FAILED(rc))              return rc;          }        }        if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE) //  If we succeeded or failed recoverably, but we were permitted to, then return success          rc = NS_OK;        return rc;      }      case nsISchemaParticle::PARTICLE_TYPE_MODEL_GROUP:       {        if (maxOccurs > 1) {  //  Todo: Try to make this thing work as an array?          return NS_ERROR_NOT_AVAILABLE; //  For now, we just try something else if we can (recoverable)        }        nsCOMPtr<nsISchemaModelGroup> modelGroup = do_QueryInterface(aParticle);        PRUint16 compositor;        rc = modelGroup->GetCompositor(&compositor);        if (NS_FAILED(rc))          return rc;        PRUint32 particleCount;        rc = modelGroup->GetParticleCount(&particleCount);        if (NS_FAILED(rc))          return rc;        PRUint32 i;        for (i = 0; i < particleCount; i++) {          nsCOMPtr<nsISchemaParticle> child;          rc = modelGroup->GetParticle(i, getter_AddRefs(child));          if (NS_FAILED(rc))            return rc;          rc = EncodeStructParticle(aEncoding, aPropertyBag, child, aAttachments, aDestination);          if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) {            if (NS_SUCCEEDED(rc)) {              return NS_OK;            }            if (rc == NS_ERROR_NOT_AVAILABLE) {  //  In a choice, recoverable model failures are OK.              rc = NS_OK;            }          }          else if (i > 0 && rc == NS_ERROR_NOT_AVAILABLE) {  //  This detects ambiguous model (non-deterministic choice which fails after succeeding on first)            return SOAP_EXCEPTION(NS_ERROR_ILLEGAL_VALUE,"SOAP_AMBIGUOUS_ENCODING","Cannot proceed due to ambiguity or error in content model");          }          if (NS_FAILED(rc))            break;        }        if (compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE)  //  If choice selected nothing, this is recoverable failure          rc = NS_ERROR_NOT_AVAILABLE;        if (minOccurs == 0 && rc == NS_ERROR_NOT_AVAILABLE)  //  If we succeeded or failed recoverably, but we were permitted to, then return success          rc = NS_OK;        return rc;                    //  Return status      }      case nsISchemaParticle::PARTICLE_TYPE_ANY://  No model available here (we may wish to handle strict versus lazy, but what does that mean with only local accessor names)      default:        break;    }  }  nsCOMPtr<nsISimpleEnumerator> e;  rc = aPropertyBag->GetEnumerator(getter_AddRefs(e));  if (NS_FAILED(rc))    return rc;  PRBool more;  rc = e->HasMoreElements(&more);  if (NS_FAILED(rc))    return rc;  while (more) {    nsCOMPtr<nsIProperty> p;    rc = e->GetNext(getter_AddRefs(p));    if (NS_FAILED(rc))      return rc;    nsAutoString name;    rc = p->GetName(name);    if (NS_FAILED(rc))      return rc;    nsCOMPtr<nsIVariant>value;    rc = p->GetValue(getter_AddRefs(value));    if (NS_FAILED(rc))      return rc;    nsCOMPtr<nsIDOMElement>result;    rc = aEncoding->Encode(value,gSOAPStrings->kEmpty,name,nsnull,aAttachments,aDestination,getter_AddRefs(result));    if (NS_FAILED(rc))      return rc;    rc = e->HasMoreElements(&more);    if (NS_FAILED(rc))      return rc;  }  return NS_OK;}