Example WebService:

/// My.SOAP
Class My.SOAP Extends %SOAP.WebService [ ProcedureBlock ]
{

/// Name des WebService.
Parameter SERVICENAME = "MyService";

/// SOAP Namespace für den WebService
Parameter NAMESPACE = "http://tempuri.org";

/// Namespaces von referenzierten Klassen werden in der WSDL verwendet.
Parameter USECLASSNAMESPACES = 1;

Method GetCustomerInfo(schema1 As My.Schema1) As My.Schema2 [ WebMethod ]
{
 set max   =schema1.MaxResult
    ,home  =schema1.HomeState
    ,office=schema1.OfficeState
    ,start =schema1.NameStartswith
 set:'max max=1
 set:office="" office=home
 set schema2=##class(My.Schema2).%New()
    ,rs=##class(%ResultSet).%New()
    ,sql="SELECT top ? %ID FROM Sample.Employee "
        _"WHERE Home_State = ? "
        _"AND Office_state = ? "
        _"AND Name %STARTSWITH ? "
       ,tSC=rs.Prepare(sql)
 set:tSC tSC=rs.Execute(max,home,office,start)
 while rs.Next()&&tSC {
   set employee=rs.GetObject()
      ,res=##class(My.Schema2Result).%New()
      ,res.HomeAddress=employee.Home
      ,res.OfficeAddress=employee.Office
      ,res.Name=employee.Name
      ,res.pid=employee.%Id()
   do schema2.Results.Insert(res)
  }
 quit schema2
}
}

Example Schema1
<?xml version="1.0" encoding="UTF-8"?>
<s:schema xmlns:s="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<s:complexType name="Schema1">
    <s:sequence>
        <s:element name="Max_Results">
            <s:simpleType>
                <s:restriction base="s:long">
                    <s:minInclusive value="1"/>
                </s:restriction>
            </s:simpleType>
        </s:element>
        <s:element name="Home-State">
            <s:simpleType>
                <s:restriction base="s:string">
                    <s:maxLength value="2"/>
                    <s:minLength value="2"/>
                </s:restriction>
            </s:simpleType>
        </s:element>
        <s:element minOccurs="0" name="Office-State" type="s:string"/>
        <s:element minOccurs="0" name="Name-Startswith" type="s:string"/>
    </s:sequence>
</s:complexType>
</s:schema>

Example Schema2

<?xml version="1.0" encoding="UTF-8"?>
<s:schema xmlns:s="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <s:complexType name="Schema2">
    <s:sequence>
        <s:element minOccurs="0" name="Results" type="ArrayOfSchema2Result"/>
    </s:sequence>
</s:complexType>
<s:complexType name="ArrayOfSchema2Result">
    <s:sequence>
        <s:element maxOccurs="unbounded" minOccurs="0" name="Schema2Result" nillable="true" type="Schema2Result"/>
    </s:sequence>
</s:complexType>
<s:complexType name="Schema2Result">
    <s:sequence>
        <s:element minOccurs="0" name="Home-Address" type="Address"/>
        <s:element minOccurs="0" name="Office-Address" type="Address"/>
        <s:element minOccurs="0" name="Person-Name" type="s:string"/>
        <s:element minOccurs="0" name="Person-ID" type="s:long"/>
    </s:sequence>
</s:complexType>
<s:complexType name="Address">
    <s:sequence>
        <s:element minOccurs="0" name="Street">
            <s:simpleType>
                <s:restriction base="s:string">
                    <s:maxLength value="80"/>
                </s:restriction>
            </s:simpleType>
        </s:element>
        <s:element minOccurs="0" name="City">
            <s:simpleType>
                <s:restriction base="s:string">
                    <s:maxLength value="80"/>
                </s:restriction>
            </s:simpleType>
        </s:element>
        <s:element minOccurs="0" name="State">
            <s:simpleType>
                <s:restriction base="s:string">
                    <s:maxLength value="2"/>
                </s:restriction>
            </s:simpleType>
        </s:element>
        <s:element minOccurs="0" name="Zip">
            <s:simpleType>
                <s:restriction base="s:string">
                    <s:maxLength value="5"/>
                </s:restriction>
            </s:simpleType>
        </s:element>
    </s:sequence>
</s:complexType>
</s:schema>

 

You may take this approach:

create an object based on Schema1: My.Schema1
create an object based on Schema2: My.Schema2

HowTo: => XML Schema Wizzard 
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

Then you may use this method.

Method GetCustomerInfo(schema1 as My.Schema1) As My.Schema2 [WebMethod]


My.Schema1 is checked as input parameter according tothe generated class
inside your Method you transform it to My.Schema2
and return it. 

The most tricky thing might be how to reply to a request that doesn't match Schema1.

I'm not an expert on callout but deep back in history I believe to remember that what ever you
transfer is in wider sense a single item. If string structured by $p() or $lb().
You my take a closer look to %XML.SAX.* classes.
The highest structure is $LB(). Which is a string under cover.
And take care of the 32k limit 

I'd suggest to use $LB() if you are not hit by the LongString limit.

why: all packaging, selection,.... is already done and "hard wired" in C++ 
with $C() you may re-invent $LB() or $Piece() or similar. And you have to do it in COS.
Same applies to local array where  you may iterate over the structure in COS again.

Nothing against COS but C++ (in COS Functions) IS faster
 

A few recommendations:
#2) save you original Global as you do otherwise.  [Just to be Save]
#1)  In Studio Copy class has a checkbox to copy Storage Definition (=Globals) . Set it.
  In the new class add ClassParameter MANAGEDEXTENT=0 ;

/// The <var>MANAGEDEXTENT</var> parameter can be set to 0 (zero) to cause the Extent Manager
/// to ignore this class. If set to 1 then the Extent Manager will register globals used by
/// the class and detect collisions. Unmanaged extents (MANAGEDEXTENT = 0) are not checked.
/// Currently, only classes using default storage (%Library.CacheStorage) can be managed.
Parameter MANAGEDEXTENT As INTEGER [ Constraint = "0,1", Flags = ENUM ] = 1;

 

So the old and the new class use the same Globals.
Now go on with #3  to #6

If you miss something in refactoring the damage should be limited as you just change names not the Storage in Globals.
Assuming the change of ClassName is all you do.

For %BuildIndices you may provide a list  or use default. it doesn't affect sequence

example from Sample.Person.1.Int

%BuildIndices(pIndexList="",pAutoPurge=1,pLockFlag=0,pJournalFlag=1,pStartID="",pEndID="",pIgnoreIndexList="") public {
if ($listlength(pIndexList)=1)&&($listget(pIndexList,1)="") return 1 }
Set class=$classname(),tBuildFlags=1,tBuildFlags(class)=$c(0,0,0,0,0,0)
Set tPtr=0,tStatus=1,pJournalFlag=''pJournalFlag
While $listnext(pIndexList,tPtr,tIndex) {
continue:tIndex=""
If '$d(^oddCOM(class,"i",tIndex)) {
Set tStatus=$select(+tStatus:$$Error^%apiOBJ(5066,class_"::"_tIndex),1:$$AppendStatus^%occSystem(tStatus,$$Error^%apiOBJ(5066,class_"::"_tIndex)))
}
}
If ('tStatus) RETURN tStatus
if $listfind(pIndexList,"$Person") set $Extract(tBuildFlags(class),1)=$c(1) }
if ((pIndexList="")||($listfind(pIndexList,"FCOL"))),'$listfind(pIgnoreIndexList,"FCOL") set $Extract(tBuildFlags(class),2)=$c(1) }
if ((pIndexList="")||($listfind(pIndexList,"NameIDX"))),'$listfind(pIgnoreIndexList,"NameIDX") set $Extract(tBuildFlags(class),3)=$c(1) }
if ((pIndexList="")||($listfind(pIndexList,"SSNKey"))),'$listfind(pIgnoreIndexList,"SSNKey") set $Extract(tBuildFlags(class),4)=$c(1) }
if ((pIndexList="")||($listfind(pIndexList,"ZipCode"))),'$listfind(pIgnoreIndexList,"ZipCode") set $Extract(tBuildFlags(class),5)=$c(1) }
if ((pIndexList="")||($listfind(pIndexList,"dobx"))),'$listfind(pIgnoreIndexList,"dobx") set $Extract(tBuildFlags(class),6)=$c(1) }
If ((pIndexList="")||($Ascii(tBuildFlags(class),5))) && '$listfind(pIgnoreIndexList,"$Person") set $extract(tBuildFlags(class),1)=$c($select((pStartID'="")||(pEndID'=""):1,1:2)) }
Quit ..%BuildIndexInternal(.pLockFlag,.pAutoPurge,.pStartID,.pEndID,.pIndexList,.tBuildFlags,"^Sample.PersonD",1,.pJournalFlag,0) }
 
 

%Save does it straight by ASSCII sorting of index names (lower after Upper case)

See %SaveData(id)  in the generated .int