建立XML来发送到服务器。

时间:2022-09-17 20:50:35

建立XML来发送到服务器。

在Unity里,我没有找到可以不添加大量排行来做这个的标准函数,所以我建立了下述机制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public  string buildXMLRPCRequest(Hashtable FieldArray,string MethodName)
{
     string  ReturnString = "" ;
 
     ReturnString    +=         "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>" +
                         "\n" + "<simpleRPC version=\"0.9\">" +
                         "\n" + "<methodCall>" +
                         "\n" + "<methodName>" + MethodName + "</methodName>" +
                         "\n" + "<vector type=\"struct\">" ;
 
     ReturnString    +=  buildNode(FieldArray);
 
     ReturnString    +=  "\n</vector>" +
                         "\n</methodCall>" +
                         "\n</simpleRPC>" ;
     return  ReturnString;
}
 
public  string buildNode(Hashtable FieldArray)
{
     string  ReturnList = "" ;
 
     foreach (DictionaryEntry Item in FieldArray)    {
 
         string  TypeName    =   "int" ;
         string  NodeType    =   "scalar" ;
 
         Type myType =   Item.Value.GetType();
         string  fieldValue  =   "" ;
 
         if (myType == typeof (string) ) {
             TypeName    =   "string" ;
             fieldValue  =   Item.Value.ToString();
         }
 
         if (myType == typeof (Hashtable) ) {
             fieldValue  =   buildNode(Item.Value as Hashtable);
             NodeType    =   "vector" ;
             TypeName    =   "struct" ;
         }
 
         if (myType == typeof (int) ) {
             fieldValue  =   Item.Value.ToString();
             TypeName    = "int" ;
         }
 
         var ThisNode    =   "\n<" + NodeType + " type=\"" + TypeName + "\" id=\"" + Item.Key + "\">" + fieldValue + "</" + NodeType + ">" ;
         ReturnList +=   ThisNode;
     }
 
     return ReturnList;
}

buildXMLRPCRequest 是用来建立 XML的。

你想要编码的字段HashTable可能包括types: int, string 或者 Hashtable的对象。它将返回精美格式化的(简单)XML-RPC字符串,准备发送到服务器。

发送

把XML发送到服务器,你需要发出带有设置为text/xml的mine类型post请求。标准C#函数没有一个能用于Unity的,但是用这种buildXMLRPCRequest逻辑输出非常有效,它所做的是:

在Unity发送:

我使用这个代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
private     void UnityPostXML(  int Staging,
                                         string WebServer,
                                         string MethodName,
                                         Hashtable   FieldArray)
     {
         string  WebServiceURL   =   "http://LIVESERVER/" ;
         if (Staging == 1) {
             WebServiceURL       =   "http://TESTSERVER" ;
         }
 
         // Encode the text to a UTF8 byte arrray
 
         string XMLRequest   =   buildXMLRPCRequest(FieldArray,MethodName);
 
         System.Text.Encoding enc = System.Text.Encoding.UTF8;
         byte[] myByteArray = enc.GetBytes(XMLRequest);
 
 
          // Get the Unity WWWForm object (a post version)
 
 
         var form = new WWWForm();
         var url = WebServiceURL;
 
         //  Add a custom header to the request.
         //  Change the content type to xml and set the character set
         var headers = form.headers;
         headers[ "Content-Type" ]= "text/xml;charset=UTF-8" ;
 
         // Post a request to an URL with our rawXMLData and custom headers
         var www = new WWW(WebServiceURL, myByteArray, headers);
 
         //  Start a co-routine which will wait until our servers comes back
 
         StartCoroutine(WaitForRequest(www));
}
 
IEnumerator WaitForRequest(WWW www)
{
     yield return www;
 
     // check for errors
     if (www.error == null )
     {
         Debug.Log( "WWW Ok!: " + www.text);
     } else {
         Debug.Log( "WWW Error: " + www.error);
     }   
}

• 用UTF8把XML编码成ByteArray

• 创建一个新的Unity WWWForm

• 创建HashTable, 存储当前的http标头,覆盖内容类型为text/xml。

• 发送lot给server

• 建立协程等待答复

不适用Unity发送

我发现使用C#(MonoDevelop)的标准版本)开发library比用Uinty开发一切简单多了。所以如果想用C#做同样的逻辑发送,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
private     string NormalXMLCall(int Staging,
                                          string WebServer,
                                          string MethodName,
                                          Hashtable Fields)
     {
         //  Figure out who to call
         string  WebServiceURL   =   "http://LIVSERVER" ;
         if (Staging == 1) {
             WebServiceURL       =   "http://TESTSERVER" ;
         }
 
         WebServiceURL           +=  WebServer;
 
         //  Build the request
 
         XmlRpcParser    parser  =   new XmlRpcParser();
         string XMLRequest       = parser.buildXMLRPCRequest(Fields,MethodName);
 
         //  Fire it off
 
         HttpWebRequest httpRequest =(HttpWebRequest)WebRequest.Create(WebServiceURL);
 
         httpRequest.Method = "POST" ;
 
         //Defining the type of the posted data as XML
         httpRequest.ContentType = "text/xml" ;
 
         // string data = xmlDoc.InnerXml;
         byte[] bytedata = Encoding.UTF8.GetBytes(XMLRequest);
 
         // Get the request stream.
         Stream requestStream = httpRequest.GetRequestStream();
 
         // Write the data to the request stream.
         requestStream.Write(bytedata, 0, bytedata.Length);
         requestStream.Close();
 
         //Get Response
         HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
 
         // Get the stream associated with the response.
         Stream receiveStream = httpResponse.GetResponseStream ();
 
         // Pipes the stream to a higher level stream reader with the required encoding format.
         StreamReader readStream = new StreamReader (receiveStream, Encoding.UTF8);
 
         string  ReceivedData    =   readStream.ReadToEnd ();
         httpResponse.Close ();
         readStream.Close ();
 
         return  ReceivedData;
     }
}

从 XML中提取数据

我写了一个简单的解析器。用于下述findNode函数的构造函数应给予原始XML数据,以及你想要找到的子节点对象。如果节点可以在*别的XML字符串找到,它将返回该节点的值,如果找不到就null。这个解析器是特定于:简单的XML-RPC,需要花点时间来解码编码的字符,那也很简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public string findNode(string Xml,string SearchForTag) {
 
     int     NestCounter     =   0;
     bool    FoundTag        =   false ;
     int     FoundTagLevel   =   0;
     string  ReturnValue     =   null ;
 
     //  Break it down by "<"
     string  []  TagArray    =   Xml.Split( '<' );
 
     for (int i=0;i<TagArray.Length;i++) {
 
         if (i>175 && i<180) {
             int Hello=1;
         }
 
         string  ThisLine    =   "<" + TagArray[i];
         if (ThisLine.Length <= 1)                                           continue ;
         if ((ThisLine.Length >= 2) && (ThisLine.Substring(0,2) == "<?" ))    continue ;
         if ((ThisLine.Length >= 3) && (ThisLine.Substring(0,3) == "<--" ))   continue ;
 
         //  It can be a vector or a scalar - vectors are full of scalars so we'll
 
         ThisLine                =   ThisLine.Replace( "  " , " " );
         ThisLine                =   ThisLine.Replace( "</" , "</" );
         string  []  FieldArray  =   ThisLine.Split(' ');
         bool    AddLineToResult =   FoundTag;
 
         //  Nest counter is the level we are operating on. We only check the first
         //  Level. When a vector is found we increase the NestCount and we won' t
         //  search for the ID
 
         if (NestCounter <= 1) { //  Initial array we are looking on level 1