C# XML转Json

Json使用第三方的LightJson


第一次提交的很多问题,在此表示歉意,这一次的应该不会让你失望。


由于目前公司的xml文件不标准,使用微软的XmlDocument的load就崩溃了,主要是里面有类似: x = 1或y=2导致,所以只能自己解析。

由于xml有如下格式:

1. <demo x=1 y="z">demo xxx </demo>,会把demo xxx 和一个固定的key(xml_inner_text)组合。

2. <demo2>demo 2</demo2>,会把demo 2和key(demo2)组合。

3. InnerText

<Description Format="FooFormat">
	desc_inner text
	line-2
	line-3
	line-4
</Description>

会把>和</之间的内容用\r\n连接,不想的话可以改。



先上效果,如果不是你想要的就关了本页面:

原始xml:

<?xml version="1.0"?>
<!DOCTYPE Test>
<Tests>
	<s_tes>
	</s_tes>
	<s_tes>asdf
	</s_tes>
	<s_tes x= 1 y = 2>asdf1111
	</s_tes>
	<singlelineclose/>
	<singlelineclose ads="111"/>
	<singlelineclose ads="111 y =  56   "/>
	<singlelineclose ads="111" y =  56   />
	<singlelineclose1 ads1="111"/>
	<abc x=1 y=2 z= 3></abc>
	<abc x1=1 y1=2 z1= 3>abc-1</abc>
	<abc x1=1 y1=2 z1=3 >abc-1</abc>
	<abc>abc-1</abc>
	<U x=1 FileName="a1\b2\c3\d4\e.s" m = 	2	 y = " y1 y2 " #z_ = " @z 2 " you=12> u test 
		U_1
	</U>
	<subtree col=3 row=5 ident=42 FileName="aa\bb\cc\dd\e1.s">
	</subtree>
	<demo x=1 y="z">demo xxx </demo>
	<demo1>demo1-1
		demo1-1
	</demo1>
	<demo2>demo 2</demo2>
  <Test Name="The First Test" x=1  y = "abc">
    <SomeText>Some simple text</SomeText>
    <SomeMoreText>More text</SomeMoreText>
    <Description Format="FooFormat">
    	desc_inner text
    	line-2
    	line-3
    	line-4
    </Description>
  </Test>
  <Test Name="Second"/>
  <otherTag0>
  </otherTag0>
  <otherTag1>abc
  </otherTag1>
  <Test Name="Third"/>
  <Test Name="Four">
  	<FourSon Name="FourSon"/>
  </Test>
</Tests>


转换后的Json:

{
	"Tests": {
		"s_tes": [
			{
			},
			"asdf",
			{
				"x": "1",
				"y": "2",
				"xml_inner_text": "asdf1111"
			}
		],
		"singlelineclose": [
			{
			},
			{
				"ads": "111"
			},
			{
				"ads": "111 y =  56   "
			},
			{
				"ads": "111",
				"y": "56"
			}
		],
		"singlelineclose1": {
			"ads1": "111"
		},
		"abc": [
			{
				"x1": "1",
				"y1": "2",
				"z1": "3",
				"xml_inner_text": "abc-1"
			},
			{
				"x1": "1",
				"y1": "2",
				"z1": "3",
				"xml_inner_text": "abc-1"
			},
			"abc-1"
		],
		"U": {
			"x": "1",
			"FileName": "a1\\b2\\c3\\d4\\e.s",
			"m": "2",
			"y": " y1 y2 ",
			"#z_": " @z 2 ",
			"you": "12",
			"xml_inner_text": " u test\r\nU_1"
		},
		"subtree": {
			"col": "3",
			"row": "5",
			"ident": "42",
			"FileName": "aa\\bb\\cc\\dd\\e1.s"
		},
		"demo": {
			"x": "1",
			"y": "z",
			"xml_inner_text": "demo xxx "
		},
		"demo1": "demo1-1\r\ndemo1-1",
		"demo2": "demo 2",
		"Test": [
			{
				"Name": "The First Test",
				"x": "1",
				"y": "abc",
				"SomeText": "Some simple text",
				"SomeMoreText": "More text",
				"Description": {
					"Format": "FooFormat",
					"xml_inner_text": "desc_inner text\r\nline-2\r\nline-3\r\nline-4"
				}
			},
			{
				"Name": "Second"
			},
			{
				"Name": "Third"
			},
			{
				"Name": "Four",
				"FourSon": {
					"Name": "FourSon"
				}
			}
		],
		"otherTag0": {
		},
		"otherTag1": "abc"
	}
}



辅助类:

TextUtil:

public static class TextUtil
{
	public static bool IsXmlHeader(string input)
	{
		string pattern = @"^<?.*?\?>{1,1}$";

		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			return true;
		}

		pattern = @"^<!DOCTYPE.*?>$";
		match = Regex.Match(input, pattern);
		if (match.Success)
		{
			return true;
		}

		return false;
	}

	public static bool IsXmlTagStart(string input, out string tagName) // <abc>
	{
		//string pattern = @"^<{1,1}/{0,0}(.+)?>{1,1}\B";
		//string pattern = @"^<{1,1}/{0,0}\w*>{1,1}\B";
		string pattern = @"^<\w+>$";

		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			int p_s = match.Value.IndexOf("<");
			int p_e = match.Value.LastIndexOf(">");
			if ((-1 == p_s) || (-1 == p_e))
			{
				tagName = null;
				return false;
			}

			tagName = match.Value.Substring(p_s + 1, p_e - p_s - 1).Trim();
			return true;
		}

		tagName = null;
		return false;
	}

	private static bool SplitXmlTagAndAttribute(ref string input, string endstr, out string tagName, out List<KeyValuePair<string, string>> attributePairs)
	{
		int endLen = endstr.Length;
		int tagLen;
		string xml;

		tagName = null;
		attributePairs = null;

		string pattern = @"^<\w+\b";
		Match match = Regex.Match(input, pattern);
		if (!match.Success)
		{
			return false;
		}

		tagName = match.Value.Substring(1); // 除<
		tagLen = tagName.Length;

		//xml = input.Substring(tagLen + 1, input.Length - tagLen - endLen - 1).Trim();
		xml = input.Substring(tagLen + 1).TrimStart();

		int pos = -1;
		string key;
		string value="";

		do
		{
			pos = xml.IndexOf("=");
			if (-1 == pos)
			{
				break;
			}

			key = xml.Substring(0, pos).Trim();
			xml = xml.Substring(pos + 1).TrimStart();
			if ('"' == xml[0])
			{
				pos = xml.IndexOf('"', 1);
				if (-1 == pos)
				{
					break;
				}
				value = xml.Substring(1, pos - 1);
			}
			else if ('\'' == xml[0]) // 开单引号
			{
				pos = xml.IndexOf('\'', 1); // 闭单引号
				if (-1 == pos)
				{
					break;
				}
				value = xml.Substring(1, pos - 1);
			}
			else if ('[' == xml[0])
			{
				pos = xml.IndexOf(']', 1);
				if (-1 == pos)
				{
					break;
				}
				value = xml.Substring(1, pos - 1);
			}
			else
			{
				pattern = @"\s";
				string[] values = Regex.Split(xml, pattern);
				if (1 < values.Count())
					value = values[0];
				else if (1 == values.Count())
				{
					int lastCloseChar = values[0].LastIndexOf(">");
					if ((values[0].Length - 1) == lastCloseChar) // 最后一个是>
					{
						value = values[0].Substring(0, values[0].Length - 1);
					}
					else
					{
						value = values[0].Substring(0, lastCloseChar);
					}
				}
				else
					value = "";

				pos = value.Length;
			}

			if (null == attributePairs)
			{
				attributePairs = new List<KeyValuePair<string, string>>();
			}
			attributePairs.Add(new KeyValuePair<string, string>(key, value));

			xml = xml.Substring(pos + 1).TrimStart();
			input = xml;
		} while ((xml != "") && (0 != xml.IndexOf(">")) && (0 != xml.IndexOf("/>")));

		return true;
	}



	public static bool IsXmlWithTagAndAttributeAndInnerTextClosed(string input, out string tagName, out List<KeyValuePair<string, string>> attributePairs, out string innerText) // 带标签,属性,innertext <abc x=y>...</abc>
	{
		tagName = null;
		attributePairs = null;
		innerText = null;

		int count0 = input.Count<char>(s => '<' == s);
		int pos = input.IndexOf("</");
		int count2 = input.Count<char>(s => '>' == s);
		int count3 = input.Count<char>(s => '=' == s);
		if ((2 != count0) || (0 >= pos) || (2 != count2) || (0 >= count3))
		{
			return false;
		}

		//string pattern = @"^<\w+\s+(\w+=(.+)?)+\s*>(?!(</)).*?</\w+>$"
		string pattern = @"^<\w+\s+(.+=.+)+\s*>(?!(</)).*?</\w+>$";
		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			string[] splitstr = Regex.Split(input, @"</.+>");
			if (2 != splitstr.Count())
			{
				return false;
			}

			string tagAttrsInner = splitstr[0];

			bool ret = SplitXmlTagAndAttribute(ref tagAttrsInner, ">", out tagName, out attributePairs);
			if (ret)
			{
				pos = tagAttrsInner.IndexOf(">");
				if (0 == pos)
				{
					innerText = tagAttrsInner.Substring(1); // 除>
				}
				else if (-1 == pos)
				{
					innerText = tagAttrsInner;
				}
			}

			return true;
		}

		return false;
	}

	public static bool IsXmlWithTagAndAttributeNotClosed(string input, out string tagName, out List<KeyValuePair<string, string>> attributePairs) // <abc m=n x="y">
	{
		tagName = null;
		attributePairs = null;

		int count0 = input.Count<char>(s => '<' == s);
		int count1 = input.IndexOf("</");
		int count2 = input.Count<char>(s => '>' == s);
		if ((2 == count0) && (0 < count1) && (2 == count2))
		{
			return false;
		}

		string pattern = @".*?/>$";
		Match match = Regex.Match(input, pattern);
		if (match.Success)
		{
			return false;
		}

		//string pattern = @"^<{1,1}/{0,0}(.+)?>{1,1}\B";
		//string pattern = @"^<\w+\s+(\w+=(.(?!(>.*</)))+)+\s*>$"
		pattern = @"^<\w+(\s+.*?=.*?)+\s*/{0,0}>$";

		Regex reg = new Regex(pattern);
		match = reg.Match(input);
		if (match.Success)
		{
			return SplitXmlTagAndAttribute(ref input, ">", out tagName, out attributePairs);
		}
		
		return false;
	}

	public static bool IsXmlSingleLineClosed(string input, out string tagName, out List<KeyValuePair<string, string>> attributePairs) // <abc x=y />
	{
		//string pattern = @"^(<{1,1}/{0,0}.*?/{1,1}>{1,1}){1,1}$";
		//string pattern = @"^<\w+(\s+.*?=.*?)*?\s*(/>){1,1}$";
		string pattern = @"^<\w+(\s+.+=.+)*?\s*/>$";

		tagName = null;
		attributePairs = null;

		int count0 = input.Count<char>(s => '<' == s);
		int pos = input.IndexOf("/>");
		int count2 = input.Count<char>(s => '>' == s);
		if ((2 == count0) || (0 >= pos) || (2 == count2))
		{
			return false;
		}

		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			return SplitXmlTagAndAttribute(ref input, "/>", out tagName, out attributePairs);
		}

		return false;
	}

	/*
	 * <abc x=1>...
	 * 
	 */
	public static bool IsXmlWithTagAndAttributeAndInnerTextNotClosed(string input, out string tagName, out List<KeyValuePair<string, string>> attributePairs, out string innerText) // <abc x=1>...
	{
		tagName = null;
		attributePairs = null;
		innerText = null;
		
		//string pattern = @"^<\w*\s+(\w+\s*=\s*\S+)+>{1,1}(.*(?!(</)))?$";
		//string pattern = @"^<\w*\s+(\w+\s*=\s*\S+)+>\B.*?$";
		string pattern = @"^<\w+\s+(\w+=(.+)?)+\s*>(?!(</)).*?$";
		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			string[] splitstr = Regex.Split(input, @">");
			if (2 != splitstr.Count())
			{
				return false;
			}

			string tagAttrs = splitstr[0] + ">";

			bool ret = SplitXmlTagAndAttribute(ref tagAttrs, ">", out tagName, out attributePairs);
			if (!ret)
			{
				return false;
			}

			innerText = splitstr[1];
			return true;
		}

		return false;
	}

	public static bool IsXmlWithTagAndInnerTextNotClosed(string input, out string tagName, out string content) // <abc>...
	{
		//string pattern = @"^<\w*?>{1,1}(?!(</)).*?(?!>)$";
		string pattern = @"^<\w+>.*?$";

		tagName = null;
		content = null;

		int pos = input.IndexOf("</");
		if (0 <= pos)
		{
			return false;
		}

		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			pos = input.IndexOf(">");
			tagName = input.Substring(1, pos - 1);
			content = input.Substring(pos + 1);
			return true;
		}

		return false;
	}

	public static bool IsXmlWithInnerTextOnly(string input, out string content)
	{
		string pattern = @"^(?!<).*?>{0,0}$";
		content = null;

		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			content = input;
			return true;
		}

		return false;
	}

	public static bool IsXmlWithTagAndInnerTextColsed(string input, out string tagName, out string content) // <abc>...</abc>
	{
		//string pattern = @"^(<{1,1}/{0,0}\w*(?!=)>{1,1}.*?<{1,1}/{1,1}\w*>{1,1}){1,1}$";
		//string pattern = @"^<\w*(?!=)>{1,1}(?!(</)).*?</\w*>$";
		string pattern = @"^<\w+>{1,1}(?!(</)).*?</\w*>$";

		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			int p_s = input.IndexOf("<");
			int p_e = input.IndexOf(">", p_s + 1);

			if ((-1 == p_s) || (-1 == p_e))
			{
				tagName = null;
				content = null;
				return false;
			}

			tagName = input.Substring(p_s + 1, p_e - p_s - 1);

			p_s = input.IndexOf("<", p_e + 1);
			if ((-1 == p_s) || (-1 == p_e))
			{
				tagName = null;
				content = null;
				return false;
			}

			content = input.Substring(p_e + 1, p_s - p_e - 1);
			return true;
		}

		tagName = null;
		content = null;
		return false;
	}

	public static bool IsXmlTagEnd(string input, out string tagName) // </abc>
	{
		//string pattern = @"^(</){1,1}\w*\b>{1,1}$";
		string pattern = @"^</\w+>$";

		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			tagName = match.Value.Substring(2, match.Value.Length - 3).Trim();
			return true;
		}

		tagName = null;
		return false;
	}

	public static bool IsXmalComment(string input)
	{
		// <!--注释-->

		string pattern = @"^(<!--){1,1}.*?(-->){1,1}$";

		Regex reg = new Regex(pattern);
		Match match = reg.Match(input);
		if (match.Success)
		{
			return true;
		}
		return false;
	}

	public static void ClearXamlComment(ref string input)
	{
		string pattern = @"^(<!--){1,1}.*?(-->){1,1}$";
		Regex reg = new Regex(pattern);
		input = Regex.Replace(input, pattern, "");
	}
}



XML解析Json类:

class XmlNode
{
	public JsonValue JsonValue;
	public string Key;
	public int Depth;

	public XmlNode(int depth)
	{
		Depth = depth;
	}
}

public class XmlToJsonParser
{
	private const string Key_InnerText = "xml_inner_text";

	private string InnerText_LineBreak = "\r\n";

	private JsonObject mJson;
	private List<XmlNode> XmlNodes;
	private int Depth = -1;

	/*
	 * 强制如下格式所有...所对应的key为Key_InnerText
	 * 1. 
	 *     <abc>....
	 *  2.
	 *     <abc> ...</abc>
	 *  3.
	 *      <abc x=y>...</abc>
	 *  4.
	 *      <abc>...
	 *          ...
	 *      </abc>
	 */
	private bool ForceAllUseInnerText = false;

	public StdXmlToJsonParser()
	{
		mJson = new JsonObject();
		XmlNodes = new List<XmlNode>();

		XmlNode root = new XmlNode(++Depth);
		root.Key = "------------------------------ xml_2_json_root_key ------------------------------";
		root.JsonValue = mJson;

		XmlNodes.Add(root);
	}

	public string ToJson(bool pretty = false)
	{
		lock (XmlNodes)
		{
			string json = mJson.ToString(pretty);
			mJson.Clear();

#if DEBUG_PRINT
			Console.WriteLine(json);
#endif
			return json;
		}
	}

	public void SetInnerTextConnector(string connector)
	{
		InnerText_LineBreak = connector;
	}

	public void SetLocalLang(string local)
	{
		mJson.Add(CodePage.LocalLangKey, local);
	}

	public void AddKeyValuPair(string key, string value)
	{
		mJson.Add(key, value);
	}

	public void Parse(string line)
	{
		string tagName;
		string innerText;
		List<KeyValuePair<string, string>> attributes;

		if (line.Contains("<LabelInf value=[#0500694A#1201001B#050089EB#\\&x = 9#12010005#05008F1D#\\& = (50-9)/50*100 = 82%#12010005#0500693D#12010005#05001ABD#05006958#12010005]>"))
		{

		}

		if (TextUtil.IsXmlHeader(line))
		{
			return;
		}
		else if (TextUtil.IsXmalComment(line)) // 注释: <!-- adfaf -->
		{
			return;
		}
		else if (TextUtil.IsXmlWithTagAndInnerTextColsed(line, out tagName, out innerText)) // 带innertext的标签: <abc>...</abc>
		{
			ParseXmlWithTagAndInnerTextClosed(tagName, innerText);
		}
		else if (TextUtil.IsXmlSingleLineClosed(line, out tagName, out attributes)) // 单行闭合标签: <abc x=y />
		{
			ParseXmlWithSingleLineClosed(tagName, attributes);
		}
		else if (TextUtil.IsXmlTagStart(line, out tagName)) // 标签开始(无属性): <abc>
		{
			ParseXmlWithStartNoAttribute(tagName);
		}
		else if (TextUtil.IsXmlTagEnd(line, out tagName)) // 标签结束: </abc>
		{
			ParseXmlWithEnd(tagName);
		}
		else if (TextUtil.IsXmlWithTagAndAttributeNotClosed(line, out tagName, out attributes)) // 带属性的标签: <abc m=n x="y">
		{
			ParseXmlWithTagAndAttributeNotClosed(tagName, attributes);
		}
		/*
		 * 前置如下格式所有...所对应的key为Key_InnerText
		 * 
		 *     <abc x=y z=d>....</abc>
		 *     
		 */
		else if (TextUtil.IsXmlWithTagAndAttributeAndInnerTextClosed(line, out tagName, out attributes, out innerText)) // 带标签,属性,innertext <abc x=y>...</abc>
		{
			ParseXmlWithTagAndAttributesAndInnerTextClosed(tagName, attributes, innerText);
		}
		else if (TextUtil.IsXmlWithTagAndAttributeAndInnerTextNotClosed(line, out tagName, out attributes, out innerText)) // <abc x=1>...
		{
			ParseXmlWithTagAndAttributeAndInnerTextNotClose(tagName, attributes, innerText);
		}
		else if (TextUtil.IsXmlWithTagAndInnerTextNotClosed(line, out tagName, out innerText)) // 非闭合带内容标签: <abc>...
		{
			ParseXmlWithTagAndInnerTextNotClosed(tagName, innerText);
		}

		/*
		 *  <abc>
		 *      tag's content
		 *  </abc>
		 */
		else if (TextUtil.IsXmlWithInnerTextOnly(line, out innerText)) // innertext:
		{
			ParseXmlWithInnerTextOnly(innerText);
		}
		else
		{
			Console.WriteLine(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + line);
		}
	}

	private void ParseXmlWithTagAndAttributesAndInnerTextClosed(string tagName, List<KeyValuePair<string, string>> attributes, string innerText)
	{
		XmlNode node = new XmlNode(++Depth);
		node.JsonValue = new JsonObject();
		node.Key = tagName;

		foreach (KeyValuePair<string, string> kv in attributes)
		{
			node.JsonValue.AsJsonObject.Add(kv.Key, kv.Value);
		}

		node.JsonValue.AsJsonObject.Add(Key_InnerText, innerText);

		AddXmlNode(node, false);
	}

	private void ParseXmlWithTagAndAttributeAndInnerTextNotClose(string tagName, List<KeyValuePair<string, string>> attributes, string innerText)
	{
		XmlNode node = new XmlNode(++Depth);
		node.JsonValue = new JsonObject();
		node.Key = tagName;

		foreach (KeyValuePair<string, string> kv in attributes)
		{
			node.JsonValue.AsJsonObject.Add(kv.Key, kv.Value);
		}

		node.JsonValue.AsJsonObject.Add(Key_InnerText, innerText);

		AddXmlNode(node, true);
	}

	private void ParseXmlWithInnerTextOnly(string innerText)
	{
		lock (XmlNodes)
		{
			XmlNode lastNode = XmlNodes[XmlNodes.Count - 1];
			JsonValue jv = lastNode.JsonValue;
			if (jv.IsJsonObject)
			{
				XmlNode ppNode = GetParentNode(lastNode);
				if (ppNode.JsonValue.IsJsonObject)
				{
					jv = ppNode.JsonValue.AsJsonObject[lastNode.Key];
					ppNode.JsonValue.AsJsonObject.Remove(lastNode.Key);

					if (!jv.AsJsonObject.ContainsKey(Key_InnerText))
					{
						jv.AsJsonObject.Add(Key_InnerText, new JsonValue(innerText));
					}
					else
					{
						JsonValue innerJv = jv.AsJsonObject[Key_InnerText];
						jv.AsJsonObject.Remove(Key_InnerText);

						string contentNew = innerJv.AsString;
						contentNew += InnerText_LineBreak + innerText;

						jv.AsJsonObject.Add(Key_InnerText, contentNew);
					}
					ppNode.JsonValue.AsJsonObject.Add(lastNode.Key, jv);
				}
			}
			else if (jv.IsString)
			{
				XmlNode ppNode = GetParentNode(lastNode);
				ppNode.JsonValue.AsJsonObject.Remove(lastNode.Key);

				string contentNew = jv.AsString;
				contentNew += InnerText_LineBreak + innerText;
				ppNode.JsonValue.AsJsonObject.Add(lastNode.Key, contentNew);
			}
		}
	}

	private void ParseXmlWithTagAndInnerTextNotClosed(string tagName, string innerText)
	{
		XmlNode node = new XmlNode(++Depth);
		node.Key = tagName;

		if (ForceAllUseInnerText)
		{
			node.JsonValue = new JsonObject();
			node.JsonValue.AsJsonObject.Add(Key_InnerText, new JsonValue(innerText));
		}
		else
		{
			node.JsonValue = new JsonValue(innerText);
		}

		AddXmlNode(node, true);
	}
	
	private void ParseXmlWithTagAndInnerTextClosed(string tagName, string innerText)
	{
		XmlNode node = new XmlNode(++Depth);
		node.Key = tagName;
		if (ForceAllUseInnerText)
		{
			node.JsonValue = new JsonObject();
			node.JsonValue.AsJsonObject.Add(Key_InnerText, new JsonValue(innerText));
		}
		else
		{
			node.JsonValue = new JsonValue(innerText);
		}

		AddXmlNode(node, false);
	}

	private void ParseXmlWithSingleLineClosed(string tagName, List<KeyValuePair<string, string>> attributes)
	{
		XmlNode node = new XmlNode(++Depth);
		node.JsonValue = new JsonObject();
		node.Key = tagName;

		if (null != attributes && 0 < attributes.Count)
		{
			foreach (KeyValuePair<string, string> kv in attributes)
			{
				node.JsonValue.AsJsonObject.Add(kv.Key, kv.Value);
			}
		}

		AddXmlNode(node, false);
	}

	private void ParseXmlWithStartNoAttribute(string tagName)
	{
		XmlNode node = new XmlNode(++Depth);
		node.JsonValue = new JsonObject();
		node.Key = tagName;

		AddXmlNode(node, true);
	}

	private void ParseXmlWithEnd(string tagName)
	{
		lock (XmlNodes)
		{
			Depth--;
			XmlNode node = XmlNodes[XmlNodes.Count - 1];
			XmlNodes.RemoveAt(XmlNodes.Count - 1);
#if DEBUG_PRINT
			Console.WriteLine("Depth: " + Depth + "Pop node: " + node.Key);
#endif
		}
	}

	private void ParseXmlWithTagAndAttributeNotClosed(string tagName, List<KeyValuePair<string, string>> attributes)
	{
		XmlNode node = new XmlNode(++Depth);
		node.JsonValue = new JsonObject();
		node.Key = tagName;

		foreach (KeyValuePair<string, string> kv in attributes)
		{
			node.JsonValue.AsJsonObject.Add(kv.Key, kv.Value);
		}

		AddXmlNode(node, true);
	}

	private void AddXmlNode(XmlNode node, bool needPush)
	{
		lock (XmlNodes)
		{
			XmlNode parentNode = GetParentNode(node);
			if (!parentNode.JsonValue.AsJsonObject.ContainsKey(node.Key)) // 不包含当前节点相同的key
			{
				parentNode.JsonValue.AsJsonObject.Add(node.Key, node.JsonValue);
			}
			else // 包含当前节点相同的key
			{
				JsonValue existJV = parentNode.JsonValue.AsJsonObject[node.Key];

				if (existJV.IsJsonObject // 已包含的是对象
					|| existJV.IsString       // 或已包含对象是字符串
					)
				{
					parentNode.JsonValue.AsJsonObject.Remove(node.Key);

					JsonValue jarr = new JsonArray();
					jarr.AsJsonArray.Add(existJV);
					jarr.AsJsonArray.Add(node.JsonValue);

					parentNode.JsonValue.AsJsonObject.Add(node.Key, jarr);
				}
				else if (existJV.IsJsonArray) // 已包含的是数组
				{
					existJV.AsJsonArray.Add(node.JsonValue);
				}
				else // 错误
				{
					Console.WriteLine("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Error xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
				}
			}

			if (needPush)
			{
				XmlNodes.Add(node);
#if DEBUG_PRINT
				Console.WriteLine("Depth: " + Depth + "Push node: " + node.Key);
#endif
			}
			else
			{
				Depth--;
			}
		}
	}

	private XmlNode GetParentNode(XmlNode node)
	{
		int lastIdx = XmlNodes.Count - 1;

		for (int i = lastIdx; i >= 0; i--)
		{
			XmlNode pnd = XmlNodes[i];
			if ((pnd.Depth + 1) == node.Depth)
			{
				return pnd;
			}
		}

		return null;
	}

	private JsonValue IsHasTheSameNode(XmlNode node)
	{
		XmlNode parentNode = GetParentNode(node);
		JsonValue parentJv;

		if (null != parentNode)
		{
			parentJv = parentNode.JsonValue;
			if (parentJv.IsJsonObject)
			{
				if (parentJv.AsJsonObject.ContainsKey(node.Key))
				{
					return parentJv;
				}
			}
			else
			{
				return parentJv;
			}
		}

		return JsonValue.Null;
	}
}




使用:

FileStream fstream = new FileStream(fileFullName, FileMode.Open, FileAccess.Read);

using (StreamReader sreader = new StreamReader(fstream, encoding))
{
    string line;

    while (!sreader.EndOfStream)
    {
        line = sreader.ReadLine();
        line = line.Trim();
        if (string.IsNullOrEmpty(line))
        {
            continue;
        }

        xmlToJsonParser.Parse(line); // 一行一行解析
    }
}
fstream.Close();

string json = xmlToJsonParser.ToJson(true);// 得到Json字符串


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneOnce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值