国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

c#示例-xml序列化和xml樹

這篇具有很好參考價值的文章主要介紹了c#示例-xml序列化和xml樹。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

序列化

由于指針和引用類型的存在,在運行中的程序中,數(shù)據(jù)不一定是整塊的。
可能東一塊西一塊散落在內(nèi)存的各個地方。

序列,是指連續(xù)且有序的一個整體。序列化就是把數(shù)據(jù)變?yōu)檫B續(xù)有序整體的過程。
經(jīng)過這樣處理后的數(shù)據(jù)就可以方便的進行傳輸和儲存了。

xml序列化

xml格式

xml是一種文本數(shù)據(jù)格式。用節(jié)點樹的形式表示數(shù)據(jù)的名字和數(shù)據(jù)的內(nèi)容。
在c#中,時間,數(shù)字,字符串及其他的基本類型內(nèi)置了直接和字符串進行轉化的方式。
而復雜類型會通過反射拆解他的成員,一直拆解直到只有基本類型為止。

public class Weapon//自帶的序列化api要求類是public的。
{
	public (int, int) Attack { get; set; }
	public float Speed { get; set; }
	public int Level { get; set; }
}
<?xml version="1.0" encoding="utf-16"?>
<Weapon xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Attack>
    <Item1>10</Item1>
    <Item2>20</Item2>
  </Attack>
  <Speed>1.5</Speed>
  <Level>3</Level>
</Weapon>

序列化api

標準庫下只提供了System.Xml.Serialization命名空間給的序列化api。
這個api不能直接序列化為string類型。只能寫入到流里面。
但是我們可以使用StringWriterStringRead,這兩個把字符串偽裝成流的東西讓他寫入。

Weapon weapon = new Weapon() { Attack = (10, 20), Speed = 1.5f, Level = 3 };

// 創(chuàng)建一個XmlSerializer對象,傳入Person類型
XmlSerializer xs = new XmlSerializer(typeof(Weapon));

// 創(chuàng)建一個StringWriter對象,用于保存XML字符串
StringWriter sw = new StringWriter();

// 調(diào)用XmlSerializer的Serialize方法,把Person對象序列化為XML字符串,并寫入StringWriter對象
xs.Serialize(sw, weapon);

// 從StringWriter對象中獲取XML字符串
string xml = sw.ToString();

// 輸出XML字符串
Console.WriteLine(xml);

為了簡化這個過程,可以制作擴展方法。

public static class Extension
{
	/// <summary>
	/// 將對象xml序列化為字符串
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="value"></param>
	/// <returns></returns> 
	public static string XmlSerialize<T>(this T value)
	{
		XmlSerializer xml = new XmlSerializer(typeof(T));
		StringWriter sw = new StringWriter();
		xml.Serialize(sw, value);
		return sw.ToString();
	}

	/// <summary>
	/// 將xml字符串反序列化
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="value"></param>
	/// <returns></returns>
	public static T XmlDeSerialize<T>(this string value)
	{
		XmlSerializer xml = new XmlSerializer(typeof(T));
		StringReader sr = new StringReader(value);
		return (T)xml.Deserialize(sr);
	}
}

特性控制序列化規(guī)則

這個序列化api

  • 要求目標類必須是具有public修飾的。
  • 他只會對public的成員進行序列化,包括字段和屬性。
  • 他要求目標類型有一個公共無參構造器
  • 通過反射進行賦值,如果目標屬性沒有set訪問器,或者自己沒有同名元素,目標屬性會保持默認值。

一些特性可以控制他的序列化規(guī)則。

元素

XmlElement特性可以指定元素名字。
在對數(shù)組或集合使用時,他會被平鋪成元素。

對數(shù)組使用前

<Person>
  <Hobbies>
    <string>讀書</string>
    <string>寫作</string>
    <string>編程</string>
  </Hobbies>
</Person>

對數(shù)組使用后

<Person>
  <Hobbies>讀書</Hobbies>
  <Hobbies>寫作</Hobbies>
  <Hobbies>編程</Hobbies>
</Person>

屬性

XmlAttribute特性可以讓一個成員以xml屬性來進行序列化。
這要求他不能是復合類型,必須像int,bool,string這樣可以不拆分直接用字符串表示的類型。

對成員使用前

<Person>
  <Age>20</Age>
</Person>

對成員使用后

<Person Age="20" />

文本

XmlText特性可以讓一個成員成為文本節(jié)點進行序列化。
因為文本節(jié)點沒法進行區(qū)分,所以一個類下最多只能有一個成員具有這個特性。
對成員使用前

<Person>
  <Age>20</Age>
</Person>

對成員使用后

<Person>
  20
</Person>

忽略

帶有XmlIgnore特性的成員在序列化和反序列化中會被無視。

排序

屬性和元素的特性,可以對屬性或元素命名。
此外,元素具有可選的Order屬性,這個屬性可以控制序列化的順序。
但是要么全都沒有這個屬性,要么全部顯式聲明這個屬性。

public class Person
{
	[XmlElement("姓名",Order =1)]
	public string Name { get; set; }
	[XmlAttribute("年齡")]
	public int Age { get; set; }
	[XmlElement(Order =0)]
	public string[] Hobbies { get; set; }
}

多態(tài)

xml可以表示更多的信息,以至于多態(tài)都可以保存。
對數(shù)組或集合使用XmlArrayItem指定類型,可以在反序列化的時候識別出類型
(序列化的時候有沒有都會保存類型)。
不過你需要提前預測可能出現(xiàn)的所有類型并一個一個進行指定。

public class Data
{
	[XmlArrayItem("字符串", typeof(string))]
	[XmlArrayItem("數(shù)字", typeof(int))]
	public object[] Datas;
}

更多

請參閱使用屬性控制 XML 序列化

xml樹

對于既存的xml字符串,可以使用System.Xml.Linq命名空間下的XElement.Parse進行解析。
對于文件,流之類的東西,可以使用XElement.Load進行讀取加載(參數(shù)是流或路徑)。

一個XElement實例可以使用ToString查看他的xml字符串,
可以使用Save保存為文件或?qū)懭氲搅髦小?/p>

xml節(jié)點

xml樹的內(nèi)容非常多,按照繼承鏈有以下類型。

  • XObject
    • XAttribute
    • XNode
      • XComment
      • XDocumentType
      • XProcessingInstruction
      • XText
        • XCData
      • XContainer
        • XDocument
        • XElement
<?xml version="1.0" encoding="utf-8"?>
<!-- 這是一個處理指令(XProcessingInstruction),用于聲明 XML 文檔的版本、編碼等信息 -->
<!-- This is a comment -->
<!-- 這是一個注釋(XComment),用于添加一些說明性的文本 -->
<!DOCTYPE Root [
	<!-- 這是一個文檔類型聲明(XDocumentType),用于定義 XML 文檔的結構和約束 -->
	<!ELEMENT Root (Child1, Child2)>
	<!-- 這是一個元素類型聲明,用于指定 Root 元素的內(nèi)容模型 -->
	<!ATTLIST Root id ID #REQUIRED>
	<!-- 這是一個屬性列表聲明,用于指定 Root 元素的屬性 -->
]>
<Root id="R1">
	<!-- 這是一個元素(XElement),表示 XML 文檔的根元素,它有一個屬性(XAttribute) id,值為 R1 -->
	<Child1>Some text</Child1>
	<!-- 這是一個元素(XElement),表示 Root 元素的第一個子元素,它有一些文本內(nèi)容(XText) -->
	<Child2 att="A1"/>
	<!-- 這是一個元素(XElement),表示 Root 元素的第二個子元素,它有一個屬性(XAttribute) att,值為 A1 -->
	<Child3><![CDATA[在這里可以輸入<>,xml,!!]]></Child3>
	<!--這是一個元素(XElement),他里面有一個CData,表示不會被轉義的文本。-->
</Root>

屬性

屬性是在元素上面,以鍵值對形式的東西。
屬性只能保存純文本信息,不能表示有層級關系的內(nèi)容。

XElement xel = new XElement("ele");
Console.WriteLine(xel);
var xat = new XAttribute("name", "張三");
xel.Add(xat);
Console.WriteLine(xel);
<ele />
<ele name="張三" />

從XElement實例上可以調(diào)用Attribute方法來查詢指定名字的特性。
可以從獲取到的Attribute上修改他,也可以從XElement直接Set指定名字的屬性。

XElement xel2 = XElement.Parse(@"<ele name=""張三"" />"); 
var xat2=xel2.Attribute("name");
xat2.Value = "999";//Value只能是string類型
Console.WriteLine(xel2);

xel2.SetAttributeValue("name",true);//這個可以是任意類型,如果是null則會刪除這個屬性。
Console.WriteLine(xel2);

Console.WriteLine(xat2);
<ele name="999" />
<ele name="true" />
name="true"

屬性也可以通過強轉轉為字符串,數(shù)字,時間等基礎類型。

XAttribute xat3 = new XAttribute("name", "16");
float? f = (float?)xat3;
Console.WriteLine(f);

基礎類型是指在xml格式中定義了的類型。是xml的基礎類型而不是c#的基礎類型。

注釋

在xml中,使用<!---->包圍的部分是注釋。注釋內(nèi)不會要求格式。

XComment comment = new XComment("這個是注釋");
Console.WriteLine(comment);
Console.WriteLine("================");
XElement xel = new XElement("root",comment); 
Console.WriteLine(xel);
<!--這個是注釋-->
================
<root>
  <!--這個是注釋-->
</root>

注釋不保存數(shù)據(jù)信息,所以不能像屬性那樣使用強轉來解析數(shù)據(jù)。

文檔類型

文檔類型是提供文檔節(jié)點驗證的說明。
通常會引用外部文件來要求xml符合格式。
如果內(nèi)聯(lián)進xml樹則如下。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

他要求note元素必須包含to,from,heading,body元素。
然后to,from,heading,body都必須是可解析的文字(不能包含嵌套的元素)。

獲取文檔約束需要通過文檔進行解析來獲取。

XDocument xDoc = XDocument.Parse(xml);//xml替換為上述的字符串

var xdt = xDoc.DocumentType; 
Console.WriteLine(xdt.InternalSubset);

驗證有專門的方法,不會出現(xiàn)在解析的時候出現(xiàn)異常。
不過如何驗證我沒查到。

處理命令

處理命令是<??>之間的內(nèi)容。
緊跟隨左邊的<?的文本會被解析為目標(Target)。
然后一個空格之后的所有內(nèi)容(即便仍然有空格拆分多塊)全部為數(shù)據(jù)(Data)。

XElement note = XElement.Parse(@"
<場景>
  <對話 text=""您想要什么?"">
    <回答 text=""紅寶石"">
      <?屬性 攻擊力 1?>
    </回答>
    <回答 text=""藍寶石"">
      <?屬性 防御力 1?>
    </回答>
    <回答 text=""血瓶"">
      <?屬性 生命 100?>
    </回答>
  </對話>
</場景>
");
var p1 = (XProcessingInstruction)note.Elements().First().Elements().First().FirstNode;
Console.WriteLine(p1.Target);//屬性
Console.WriteLine(p1.Data);//攻擊力 1

文本

在元素下的文本為文本節(jié)點。

XElement note = XElement.Parse(@"
<root>
  你好,世界
</root>
");
var t1 =(XText) note.FirstNode;

Console.WriteLine(t1.Value);

但是只要沒有貼合元素的開閉標簽,都會包含。
例如這里的標簽和文字之間有換行。所以這里的文本內(nèi)容會包含換行符。

轉義文本

通常情況下,xml內(nèi)容是不能包含尖括號,引號之類的東西。如果要書寫則需要轉義。
但是如果是文本元素,可以通過<![CDATA[]]>聲明轉義文本。
因為他的開啟和結束符號很多。所以通常請看下,里面的東西都不會有歧義的解讀。

XElement note = XElement.Parse(@"
<root>
  <![CDATA[這是一個xml的標簽:<a int=""3"" />]]>
</root>
");
var t1 =(XCData) note.FirstNode;

Console.WriteLine(t1.Value);

這個節(jié)點只有可能是文本節(jié)點,所以這個類型是從XText派生的。

文檔

文檔和元素的共同基類XContainer是指里面可能嵌套東西的。
只是用來解析一個元素,使用文檔和元素都可以。
但是文檔另外可能包含xml開頭的說明符。
<?xml version="1.0" encoding="UTF-8"?>這表示使用1.0語法的xml,使用utf-8編碼。

XDeclaration declaration = new XDeclaration("1.0", "UTF-8", null);

元素

xml元素是xml樹中最重要的東西,可以表示層級,可以包含內(nèi)容,可以攜帶屬性。
一個元素可以嵌套多個同名元素,所以不像json可以使用索引器訪問內(nèi)容。
以下示例展示xml元素的常用方法。

XElement letters = XElement.Parse(@"
<letters>
  <letter from=""張三"" to=""李四"" date=""2022-01-30"">
    <subject>問候</subject>
    <body>李四,你好!最近過得怎么樣?</body>
  </letter>
  <letter from=""李四"" to=""張三"" date=""2022-02-01"">
    <subject>回復</subject>
    <body>張三,你好!我最近很好,謝謝你的關心。</body>
  </letter>
</letters>
");
foreach (var item in letters.Descendants().Where(x=>x.Name=="subject"))
{//Descendants方法可以遞歸獲取所有子節(jié)點。
	Console.WriteLine(item.Value);
}

Console.WriteLine(letters.Elements("letter").First().Value);
//Elements方法為獲取所有指定名字的直屬子節(jié)點??梢圆惶蠲?。

letters.SetAttributeValue("count",4);
//SetAttributeValue方法可以修改屬性的值,如果沒有這個屬性會添加。如果使用null值會移除屬性。

元素可以使用Add方法,或者在構造器的名字后面加入多個值。

  • 如果是XObject家族的,會被嵌入進樹里面。
  • 對于數(shù)組,可迭代類型的東西,會拆開后對里面的元素依次添加。
  • 其他類型的數(shù)據(jù),會使用ToString轉文字后加入進去。所以復雜類型需要自己先序列化,然后解析為xml節(jié)點,再添加xml節(jié)點。

XName

雖然在上面的例子里面,屬性和節(jié)點的名字都是直接使用字符串類型。
但實際上構造器接受的是XName類型,他細分為命名空間和名字。

XElement xel = new XElement("{火蜥蜴戰(zhàn)隊}張三");
Console.WriteLine(xel);
//<張三 xmlns="火蜥蜴戰(zhàn)隊" />

XName xn = xel.Name;
Console.WriteLine(xn.NamespaceName); //火蜥蜴戰(zhàn)隊
Console.WriteLine(xn.LocalName);     //張三

XName類型的構造器是私有的。但是有一個從string而來的隱式轉換。
在if語句中可以直接使用==進行判斷,
但是在switch語句中,需要從他的屬性里訪問出他的名字。
因為隱式轉換是一個操作過程,不屬于常量,不能用于switch。

一個節(jié)點有明明空間時,他的子節(jié)點默認和他是相同的命名空間。
所以命名空間不同的都要標識,包括命名空間為""的。

XElement xel = new XElement("{火蜥蜴戰(zhàn)隊}張三"
	, new XElement("李四")
	, new XElement("{不死鳥戰(zhàn)隊}王五")
	, new XElement("{火蜥蜴戰(zhàn)隊}趙六"));
Console.WriteLine(xel);
/*
<張三 xmlns="火蜥蜴戰(zhàn)隊">
  <李四 xmlns="" />
  <王五 xmlns="不死鳥戰(zhàn)隊" />
  <趙六 />
</張三>
*/

用于屬性上時,會再額外聲明一個命名空間屬性。
這個額外的命名空間屬性是可以更改的。文章來源地址http://www.zghlxwxcb.cn/news/detail-563383.html

XElement xel = new XElement("{火蜥蜴戰(zhàn)隊}張三"
	, new XAttribute("{2023}職務","隊長")
	, new XElement("李四"
		,new XAttribute("{2023}職務","副隊長")
	)
); 
Console.WriteLine(xel);
/*
<張三 p1:職務="隊長" xmlns:p1="2023" xmlns="火蜥蜴戰(zhàn)隊">
  <李四 p1:職務="副隊長" xmlns="" />
</張三>
*/
Console.WriteLine("===========");
xel.SetAttributeValue(XNamespace.Xmlns + "zhang", "2023");
//XNamespace.Xmlns 這個靜態(tài)變量是聲明命名空間的xml命名空間。和一個字符串相加以后會變成XName
Console.WriteLine(xel);
/*
<張三 zhang:職務="隊長" xmlns:zhang="2023" xmlns="火蜥蜴戰(zhàn)隊">
  <李四 zhang:職務="副隊長" xmlns="" />
</張三>
*/

到了這里,關于c#示例-xml序列化和xml樹的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 序列化協(xié)議:JSON和XML

    作者:CARROT 鏈接:https://www.zhihu.com/question/604811576/answer/3100483698 來源:知乎 著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。 ? json和xml都是數(shù)據(jù)傳輸?shù)母袷健1热缥覀冮_發(fā)過程中需要和網(wǎng)頁交換數(shù)據(jù),我們既可以使用json格式也可以使用xml格式。再

    2024年02月11日
    瀏覽(20)
  • C#: Json序列化和反序列化,集合為什么多出來一些元素?

    C#: Json序列化和反序列化,集合為什么多出來一些元素?

    如下面的例子,很容易看出問題: 如果類本身的無參構造函數(shù),?就添加了一些元素,序列化,再反序列化,會導致元素增加。 如果要避免,必須添加: new JsonSerializerSettings() { ObjectCreationHandling = ObjectCreationHandling.Replace }

    2024年02月10日
    瀏覽(20)
  • C#使用MongoDB-第二章 序列化

    C#使用MongoDB-第二章 序列化

    這里在C#中所使用的連接MongoDB數(shù)據(jù)庫的依賴庫為 MongoDB.Driver ,使用前先到Nuget中進行安裝。 默認情況下,在我們對MongoDB數(shù)據(jù)庫進行CRUD時,MongoDB.Driver(以后簡稱驅(qū)動庫)會自動為我們根據(jù)屬性、屬性類型,將實體類型轉換為對應的BSON。 實體類 對應的BSON 1、主鍵Id 默認情況

    2024年01月22日
    瀏覽(22)
  • C#對象二進制序列化優(yōu)化:位域技術實現(xiàn)極限壓縮

    目錄 1. 引言 2. 優(yōu)化過程 2.1. 進程對象定義與初步分析 2.2. 排除Json序列化 2.3. 使用BinaryWriter進行二進制序列化 2.4. 數(shù)據(jù)類型調(diào)整 2.5. 再次數(shù)據(jù)類型調(diào)整與位域優(yōu)化 3. 優(yōu)化效果與總結 在操作系統(tǒng)中,進程信息對于系統(tǒng)監(jiān)控和性能分析至關重要。假設我們需要開發(fā)一個監(jiān)控程序

    2024年01月22日
    瀏覽(23)
  • Protobuf-net:C#高效序列化工具,助力接口傳輸與前端解析

    Protobuf-net:C#高效序列化工具,助力接口傳輸與前端解析

    ? 概述: Protobuf-net是C#中高效的二進制序列化工具,以緊湊、跨語言支持和卓越性能著稱。通過定義消息類型、序列化和反序列化實現(xiàn)數(shù)據(jù)傳輸,并可適用于Web接口。前端可使用protobuf.js庫解析Protobuf格式數(shù)據(jù)。 Protobuf-net(Protocol Buffers)是一種高效的二進制序列化工具,具有

    2024年03月09日
    瀏覽(33)
  • Go語言網(wǎng)絡編程入門:TCP、HTTP、JSON序列化、Gin、WebSocket、RPC、gRPC示例

    Go語言網(wǎng)絡編程入門:TCP、HTTP、JSON序列化、Gin、WebSocket、RPC、gRPC示例

    在本文中,我們將介紹Go語言中的網(wǎng)絡編程的不同方式,包括TCP、HTTP、Gin框架、WebSocket、RPC、gRPC的介紹與連接實例,并對所有示例代碼都給出了詳細的注釋,最后對每種模式進行了總結。 TCP(傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,提供

    2024年02月16日
    瀏覽(28)
  • 【Java萬花筒】選擇最適合您的數(shù)據(jù)序列化格式:比較 Avro、Protocol Buffers、JSON、XML、MessagePack和BSON

    在當今數(shù)據(jù)驅(qū)動的世界中,高效地處理和傳輸數(shù)據(jù)變得至關重要。選擇合適的數(shù)據(jù)序列化格式對于數(shù)據(jù)存儲、通信和處理的性能至關重要。本文將介紹并比較幾種常用的數(shù)據(jù)序列化格式,包括Apache Avro、Protocol Buffers、JSON、XML、MessagePack和BSON。通過了解它們的概述、特點、應用

    2024年02月20日
    瀏覽(19)
  • 【序列化與反序列化】關于序列化與反序列化MessagePack的實踐

    【序列化與反序列化】關于序列化與反序列化MessagePack的實踐

    在進行序列化操作之前,我們還對系統(tǒng)進行壓測,通過 jvisualvm 分析cpu,線程,垃圾回收情況等;運用火焰圖 async-profiler 分析系統(tǒng)性能,找出程序中占用CPU資源時間最長的代碼塊。 代碼放置GitHub:https://github.com/nateshao/leetcode/tree/main/source-code/src/main/java/com/nateshao/source/code/ser

    2024年02月11日
    瀏覽(28)
  • 【網(wǎng)絡】序列化反序列化

    【網(wǎng)絡】序列化反序列化

    在前文《網(wǎng)絡編程套接字》中,我們實現(xiàn)了服務器與客戶端之間的字符串通信,這是非常簡單的通信,在實際使用的過程中,網(wǎng)絡需要傳輸?shù)牟粌H僅是字符串,更多的是結構化的數(shù)據(jù)(類似于 class , struct 類似的數(shù)據(jù))。 那么我們應該怎么發(fā)送這些結構化的數(shù)據(jù)呢? 如果我們

    2024年02月05日
    瀏覽(29)
  • 序列化,反序列化之實例

    序列化,反序列化之實例

    介紹文章 __construct() 當一個對象創(chuàng)建時自動調(diào)用 __destruct() 當對象被銷毀時自動調(diào)用 (php絕大多數(shù)情況下會自動調(diào)用銷毀對象) __sleep() 使**用serialize()函數(shù)時觸發(fā) __wakeup 使用unserialse()**函數(shù)時會自動調(diào)用 __toString 當一個對象被當作一個字符串被調(diào)用 __call() 在對象上下文中調(diào)用不

    2024年02月14日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包