123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Text;
- namespace FairyGUI.Utils
- {
- public enum XMLTagType
- {
- Start,
- End,
- Void,
- CDATA,
- Comment,
- Instruction
- }
- /// <summary>
- ///
- /// </summary>
- public class XMLIterator
- {
- public static string tagName;
- public static XMLTagType tagType;
- public static string lastTagName;
- static string source;
- static int sourceLen;
- static int parsePos;
- static int tagPos;
- static int tagLength;
- static int lastTagEnd;
- static bool attrParsed;
- static bool lowerCaseName;
- static StringBuilder buffer = new StringBuilder();
- static Dictionary<string, string> attributes = new Dictionary<string, string>();
- const string CDATA_START = "<![CDATA[";
- const string CDATA_END = "]]>";
- const string COMMENT_START = "<!--";
- const string COMMENT_END = "-->";
- public static void Begin(string source, bool lowerCaseName = false)
- {
- XMLIterator.source = source;
- XMLIterator.lowerCaseName = lowerCaseName;
- sourceLen = source.Length;
- parsePos = 0;
- lastTagEnd = 0;
- tagPos = 0;
- tagLength = 0;
- tagName = null;
- }
- public static bool NextTag()
- {
- int pos;
- char c;
- tagType = XMLTagType.Start;
- buffer.Length = 0;
- lastTagEnd = parsePos;
- attrParsed = false;
- lastTagName = tagName;
- while ((pos = source.IndexOf('<', parsePos)) != -1)
- {
- parsePos = pos;
- pos++;
- if (pos == sourceLen)
- break;
- c = source[pos];
- if (c == '!')
- {
- if (sourceLen > pos + 7 && source.Substring(pos - 1, 9) == CDATA_START)
- {
- pos = source.IndexOf(CDATA_END, pos);
- tagType = XMLTagType.CDATA;
- tagName = string.Empty;
- tagPos = parsePos;
- if (pos == -1)
- tagLength = sourceLen - parsePos;
- else
- tagLength = pos + 3 - parsePos;
- parsePos += tagLength;
- return true;
- }
- else if (sourceLen > pos + 2 && source.Substring(pos - 1, 4) == COMMENT_START)
- {
- pos = source.IndexOf(COMMENT_END, pos);
- tagType = XMLTagType.Comment;
- tagName = string.Empty;
- tagPos = parsePos;
- if (pos == -1)
- tagLength = sourceLen - parsePos;
- else
- tagLength = pos + 3 - parsePos;
- parsePos += tagLength;
- return true;
- }
- else
- {
- pos++;
- tagType = XMLTagType.Instruction;
- }
- }
- else if (c == '/')
- {
- pos++;
- tagType = XMLTagType.End;
- }
- else if (c == '?')
- {
- pos++;
- tagType = XMLTagType.Instruction;
- }
- for (; pos < sourceLen; pos++)
- {
- c = source[pos];
- if (Char.IsWhiteSpace(c) || c == '>' || c == '/')
- break;
- }
- if (pos == sourceLen)
- break;
- buffer.Append(source, parsePos + 1, pos - parsePos - 1);
- if (buffer.Length > 0 && buffer[0] == '/')
- buffer.Remove(0, 1);
- bool singleQuoted = false, doubleQuoted = false;
- int possibleEnd = -1;
- for (; pos < sourceLen; pos++)
- {
- c = source[pos];
- if (c == '"')
- {
- if (!singleQuoted)
- doubleQuoted = !doubleQuoted;
- }
- else if (c == '\'')
- {
- if (!doubleQuoted)
- singleQuoted = !singleQuoted;
- }
- if (c == '>')
- {
- if (!(singleQuoted || doubleQuoted))
- {
- possibleEnd = -1;
- break;
- }
- possibleEnd = pos;
- }
- else if (c == '<')
- break;
- }
- if (possibleEnd != -1)
- pos = possibleEnd;
- if (pos == sourceLen)
- break;
- if (source[pos - 1] == '/')
- tagType = XMLTagType.Void;
- tagName = buffer.ToString();
- if (lowerCaseName)
- tagName = tagName.ToLower();
- tagPos = parsePos;
- tagLength = pos + 1 - parsePos;
- parsePos += tagLength;
- return true;
- }
- tagPos = sourceLen;
- tagLength = 0;
- tagName = null;
- return false;
- }
- public static string GetTagSource()
- {
- return source.Substring(tagPos, tagLength);
- }
- public static string GetRawText(bool trim = false)
- {
- if (lastTagEnd == tagPos)
- return string.Empty;
- else if (trim)
- {
- int i = lastTagEnd;
- for (; i < tagPos; i++)
- {
- char c = source[i];
- if (!char.IsWhiteSpace(c))
- break;
- }
- if (i == tagPos)
- return string.Empty;
- else
- return source.Substring(i, tagPos - i).TrimEnd();
- }
- else
- return source.Substring(lastTagEnd, tagPos - lastTagEnd);
- }
- public static string GetText(bool trim = false)
- {
- if (lastTagEnd == tagPos)
- return string.Empty;
- else if (trim)
- {
- int i = lastTagEnd;
- for (; i < tagPos; i++)
- {
- char c = source[i];
- if (!char.IsWhiteSpace(c))
- break;
- }
- if (i == tagPos)
- return string.Empty;
- else
- return XMLUtils.DecodeString(source.Substring(i, tagPos - i).TrimEnd());
- }
- else
- return XMLUtils.DecodeString(source.Substring(lastTagEnd, tagPos - lastTagEnd));
- }
- public static bool HasAttribute(string attrName)
- {
- if (!attrParsed)
- {
- attributes.Clear();
- ParseAttributes(attributes);
- attrParsed = true;
- }
- return attributes.ContainsKey(attrName);
- }
- public static string GetAttribute(string attrName)
- {
- if (!attrParsed)
- {
- attributes.Clear();
- ParseAttributes(attributes);
- attrParsed = true;
- }
- string value;
- if (attributes.TryGetValue(attrName, out value))
- return value;
- else
- return null;
- }
- public static string GetAttribute(string attrName, string defValue)
- {
- string ret = GetAttribute(attrName);
- if (ret != null)
- return ret;
- else
- return defValue;
- }
- public static int GetAttributeInt(string attrName)
- {
- return GetAttributeInt(attrName, 0);
- }
- public static int GetAttributeInt(string attrName, int defValue)
- {
- string value = GetAttribute(attrName);
- if (value == null || value.Length == 0)
- return defValue;
- int ret;
- if (int.TryParse(value, out ret))
- return ret;
- else
- return defValue;
- }
- public static float GetAttributeFloat(string attrName)
- {
- return GetAttributeFloat(attrName, 0);
- }
- public static float GetAttributeFloat(string attrName, float defValue)
- {
- string value = GetAttribute(attrName);
- if (value == null || value.Length == 0)
- return defValue;
- float ret;
- if (float.TryParse(value, out ret))
- return ret;
- else
- return defValue;
- }
- public static bool GetAttributeBool(string attrName)
- {
- return GetAttributeBool(attrName, false);
- }
- public static bool GetAttributeBool(string attrName, bool defValue)
- {
- string value = GetAttribute(attrName);
- if (value == null || value.Length == 0)
- return defValue;
- bool ret;
- if (bool.TryParse(value, out ret))
- return ret;
- else
- return defValue;
- }
- public static Dictionary<string, string> GetAttributes(Dictionary<string, string> result)
- {
- if (result == null)
- result = new Dictionary<string, string>();
- if (attrParsed)
- {
- foreach (KeyValuePair<string, string> kv in attributes)
- result[kv.Key] = kv.Value;
- }
- else //这里没有先ParseAttributes再赋值给result是为了节省复制的操作
- ParseAttributes(result);
- return result;
- }
- public static Hashtable GetAttributes(Hashtable result)
- {
- if (result == null)
- result = new Hashtable();
- if (attrParsed)
- {
- foreach (KeyValuePair<string, string> kv in attributes)
- result[kv.Key] = kv.Value;
- }
- else //这里没有先ParseAttributes再赋值给result是为了节省复制的操作
- ParseAttributes(result);
- return result;
- }
- static void ParseAttributes(IDictionary attrs)
- {
- string attrName;
- int valueStart;
- int valueEnd;
- bool waitValue = false;
- int quoted;
- buffer.Length = 0;
- int i = tagPos;
- int attrEnd = tagPos + tagLength;
- if (i < attrEnd && source[i] == '<')
- {
- for (; i < attrEnd; i++)
- {
- char c = source[i];
- if (Char.IsWhiteSpace(c) || c == '>' || c == '/')
- break;
- }
- }
- for (; i < attrEnd; i++)
- {
- char c = source[i];
- if (c == '=')
- {
- valueStart = -1;
- valueEnd = -1;
- quoted = 0;
- for (int j = i + 1; j < attrEnd; j++)
- {
- char c2 = source[j];
- if (Char.IsWhiteSpace(c2))
- {
- if (valueStart != -1 && quoted == 0)
- {
- valueEnd = j - 1;
- break;
- }
- }
- else if (c2 == '>')
- {
- if (quoted == 0)
- {
- valueEnd = j - 1;
- break;
- }
- }
- else if (c2 == '"')
- {
- if (valueStart != -1)
- {
- if (quoted != 1)
- {
- valueEnd = j - 1;
- break;
- }
- }
- else
- {
- quoted = 2;
- valueStart = j + 1;
- }
- }
- else if (c2 == '\'')
- {
- if (valueStart != -1)
- {
- if (quoted != 2)
- {
- valueEnd = j - 1;
- break;
- }
- }
- else
- {
- quoted = 1;
- valueStart = j + 1;
- }
- }
- else if (valueStart == -1)
- {
- valueStart = j;
- }
- }
- if (valueStart != -1 && valueEnd != -1)
- {
- attrName = buffer.ToString();
- if (lowerCaseName)
- attrName = attrName.ToLower();
- buffer.Length = 0;
- attrs[attrName] = XMLUtils.DecodeString(source.Substring(valueStart, valueEnd - valueStart + 1));
- i = valueEnd + 1;
- }
- else
- break;
- }
- else if (!Char.IsWhiteSpace(c))
- {
- if (waitValue || c == '/' || c == '>')
- {
- if (buffer.Length > 0)
- {
- attrName = buffer.ToString();
- if (lowerCaseName)
- attrName = attrName.ToLower();
- attrs[attrName] = string.Empty;
- buffer.Length = 0;
- }
- waitValue = false;
- }
- if (c != '/' && c != '>')
- buffer.Append(c);
- }
- else
- {
- if (buffer.Length > 0)
- waitValue = true;
- }
- }
- }
- }
- }
|