私は実際に私自身の質問に答えています。Unity3D XML(-RPC)とC#
私はこれをやろうとしたが、これを解決するのに約1週間かかりましたが、私はXMLを使用したい別の人がいれば)Unityで - 私は彼らに数週間の面倒を保存します。
私がやりたいことは、リーダーボードなどのゲームサーバーの1つに話すことです。このサーバはXML-RPCを「話す」と私はすぐにそれがUnityでは簡単ではないことを理解しました。当社のサーバーに
を送信するために
私は実際に私自身の質問に答えています。Unity3D XML(-RPC)とC#
私はこれをやろうとしたが、これを解決するのに約1週間かかりましたが、私はXMLを使用したい別の人がいれば)Unityで - 私は彼らに数週間の面倒を保存します。
私がやりたいことは、リーダーボードなどのゲームサーバーの1つに話すことです。このサーバはXML-RPCを「話す」と私はすぐにそれがUnityでは簡単ではないことを理解しました。当社のサーバーに
を送信するために
ビルドXML Iは、オーバーヘッドの非常に大きな金額を追加せずにこれを行うにはユニティでの標準的な機能を見つけることができませんでした。だから私は代わりに次の手順を構築する。
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;
}
XMLを構築するためにbuildXMLRPCRequestが使用されます。エンコードするフィールドを持つHashTableを渡します。エンコードするフィールドには、int型、string型、Hashtable型のオブジェクトが含まれます。それは私たちのサーバーに行く準備ができている美しく形式化された(単純な)XML-RPC文字列を返します。
当社のサーバーにXMLを送信するには
を送るには、テキスト/ xmlに設定MIMEタイプを持つPOSTリクエストを発行する必要があります。 Unityで標準のC#メソッドを使用することはできませんが、これを使用してbuildXMLRPCRequestロジックの出力が完全に機能します。何それがない:UTF8
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);
}
}
はユニティ
に送信する私はこのコードを使用HashTable、現在のhttpヘッダー(存在する場合)を格納し、コンテンツタイプをtext/xmlに上書きする
せずに送信
を待っコルーチンを設定
から
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;
}
}
抽出データは、私は、単純なパーサを書きました。以下のfindNode関数のコンストラクタには、検索する生のXMLデータと子ノードオブジェクトを指定する必要があります。そのノードがXML文字列の最上位レベルにある場合はそのノードの値(文字列)を返し、見つからない場合はnullを返します。このパーサーは "Simple XML-RPC"に固有であり、エンコードされた文字をデコードするためには少しの作業が必要ですが、追加するのは簡単なはずです。
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
for (int a=0;a<FieldArray.Length;a++) {
string ThisTag = FieldArray[a];
string [] TagValue = ThisTag.Split("=\"".ToCharArray(),5);
// Every TagValue is xx=yy pair... we want "ID=\"xxx\"
if (TagValue.Length >= 3) {
string TagName = TagValue[2];
if (TagName == SearchForTag) {
FoundTag = true;
FoundTagLevel = NestCounter;
// This could be a vector or Scalar so find the ">" in this string
// and start adding from there
int TerminatePos = ThisLine.IndexOf(">");
if ((TerminatePos >= 0) && (TerminatePos < ThisLine.Length)) {
ReturnValue = ThisLine.Substring(TerminatePos+1);
}
break;
}
}
}
}
if (FieldArray.Length > 0) {
string ThisField = FieldArray[0].ToLower();
/*
* If we are in the loop where we have found the tag,
* we haven't changed level and this is the end of a scalar it must
* mean that the tag was a scalar so we can safely leave now.
*/
if ((FoundTag) && (FoundTagLevel == NestCounter) && (ThisField == "</scalar>")) {
break;
// return ReturnValue;
}
// If we end or leave a vector we change the NestCounter
if (ThisField.IndexOf("<vector") >= 0) {
NestCounter++;
}
else if (ThisField.IndexOf("</vector>") >= 0) {
NestCounter--;
}
}
// If we have found our tag and the nest counte goes below the level
// we where looking at - it's time to leave
if (FoundTag) {
if (NestCounter <= FoundTagLevel) {
break;
//return ReturnValue;
}
}
if (AddLineToResult) {
ReturnValue += ThisLine;
}
}
// You may wanna do some url decoding here....
return ReturnValue;
}
+1非常に詳細な、そして非常にうまく行って、私は将来 – Spooks
+1やブックマーク、印加:-)でこれを必要と確信しています – Kay