C#7 入门实用指南(四)
原文:
zh.annas-archive.org/md5/0D2F44FACA4630D8785DF55498F3E611译者:飞龙
第二十七章:创建和使用 XML 文件
在本章中,我们将介绍 XML(可扩展标记语言)的基础知识。基本上,这是一种在互联网上结构化信息的方式。XML 的一个有用的方面是它是可扩展的,这意味着您可以创建自己的标签。
在 HTML 中添加按钮
启动一个项目。在<html>中唯一要放置的是一个Button控件。要做到这一点,转到工具箱,在搜索字段中输入but,然后将Button控件拖放到以<form id=...开头的行下面。将按钮上的文本更改为Read XML。
编写 XML
现在您需要一个可以阅读的文件。为此,转到解决方案资源管理器,右键单击网站的名称。在下拉菜单中选择添加,然后选择添加新项...。在搜索字段中输入xml,并确保选择 Visual C#中标有 XML 文件的 XML 文件。您的XMLFile.xml的起始屏幕应该如图 27.1.1所示:
图 27.1.1:XMLFile.xml 的起始屏幕
现在让我们逐行创建代码,这样您就可以看到到底发生了什么。基本上,就像在 HTML 中一样,XML 中有元素、元素的嵌套和属性。
首先,想象一下您有一家书店。在 XML 中,您可以创建自己的标签。因此,接下来输入以下内容:
<bookstore>
注意它自动创建了开放和关闭标签:<bookstore> </bookstore>。在这些标签之间插入几行空白。
当然,您的书店里有书,所以在第一个<bookstore>标签下面输入以下内容:
<book type="eBook">
一本书可能是传统的教科书,也可能是电子书。因此,我们将指定一个类型属性,并将其设置为我们第一本书的eBook。
现在让我们谈谈存储在<book type="eBook">下的一些元素。显然,一个基本的项目是书名,所以输入以下内容:
<booktitle>The Great Way</booktitle>
我们将这本书称为The Great Way。
在下一个阶段,自然地,您要输入作者,所以输入以下内容:
<author>Bob Jones</author>
因此,我们的书是由Bob Jones写的。
最后一项当然是价格,我们将说这个案例中是$10.00,所以输入以下内容:
<price>10.00</price>
这些信息提供了第一个书籍元素,正如您所看到的,它由称为<booktitle>、<author>和<price>的子元素组成。
现在让我们再做一本书,只是为了多样性,如下所示:
<book type="traditional">
<booktitle>Happy People</booktitle>
<author>Mary Jenkins</author>
<price>11.00</price>
</book>
我们的简单 XML 文件如下代码块所示:
<?xml version="1.0" encoding="utf-8" ?>
<bookstore>
<book type="eBook">
<booktitle>The Great Way</booktitle>
<author>Bob Jones</author>
<price>10.00</price>
</book>
<book type="traditional">
<booktitle>Happy People</booktitle>
<author>Mary Jenkins</author>
<price>11.00</price>
</book>
</bookstore>
再次记住,XML 是可扩展的,因为您可以创建自己的标签,标记因为它具有类似 HTML 的结构,当然,它是一种语言。
现在,右键单击标有XMLFile.xml的选项卡,并从下拉菜单中选择复制完整路径。我们将很快使用这个路径。(如果您将鼠标悬停在XMLFile.xml选项卡上,可以看到完整路径,但它很长且难以记住,因此最好右键单击并选择复制完整路径。)
现在点击 HTML 中的Default.aspx选项卡,切换到设计视图,然后双击读取 XML 按钮。这会打开Default.aspx.cs中的事件处理代码。删除Page_Load存根。该项目的起始代码的相关部分应该如图 27.1.2所示:
图 27.1.2:该项目的起始代码
添加一个命名空间
让我们首先添加一个命名空间。您需要一个新的,所以在文件顶部附近的using System之后输入以下内容:
using System.Xml.Linq;
您将在编码中使用此命名空间。(您可以折叠public partial class...上面的所有代码。)
将 XML 文件加载到您的程序中
在下一个阶段,在以protected void Button1_Click...开头的行下面的一对大括号中输入以下内容:
XElement fromFile = XElement.Load(@"C:\Users\towsi\Documents\Visual Studio 2015\WebSites\CSharpTemplateUpdated76143\XMLFile.xml");
你想要加载XElement fromFile,所以你说XElement.Load()。然后,在括号内,你放置@符号使其成为原始字符串,然后是双引号。现在你需要利用从XMLFile.xml中复制的路径,这样你就可以从文件中加载 XML。所以,将路径粘贴在一对""符号之间。这将允许你加载可扩展标记文件。现在将鼠标悬停在XElement上。它说,类 System.Xml.Linq.XElement,表示 XML 元素。
遍历 XML 文件的内容
现在,输入以下内容:
foreach(XElement childElement in fromFile.Elements())
当你将鼠标悬停在这一行末尾的Elements上时,你会发现它是一个函数,返回的是 IEnumerable,所以你可以遍历它的内容,其中每个成员都是一个元素。
显示结果
现在你可以显示它们,所以在一对大括号之间输入以下内容:
首先,你需要书的类型。要获取它,在你输入sampLabel.Text += $"<br>Book Type:之后,你说{childElement.Attribute("type"),然后获取值,你输入.Value}";:
sampLabel.Text += $"<br>Book Type:{childElement.Attribute("type").Value}";
现在,要获取作者,你使用{childElement.Element("author")}";,如下所示:
sampLabel.Text += $"<br>{childElement.Element("author")}";
这就是你可以将所有元素取出来的方法。在这个阶段,你可以直接复制并粘贴这行代码,因为对于书名和书价来说基本上是一样的。
对于书名,你可以这样说:{childElement.Element("booktitle")}";,如下所示:
sampLabel.Text += $"<br>{childElement.Element("booktitle")}";
对于价格,你可以这样说:{childElement.Element("price")}";,如下所示:
sampLabel.Text += $"<br>{childElement.Element("price")}";
最后,为了分隔开,你可以使用"<br><hr/>";,如下所示:
sampLabel.Text += $"<br><hr/>";
运行程序
现在让我们在这里试一下,在浏览器中打开它。记住,你实际上是在将 XML 读入网页。这是我们的目标。点击“读取 XML”按钮。结果显示在图 27*.1.3*中:
图 27.1.3:运行程序的结果
信息被报告的方式与你输入的方式完全一样,这是你所期望的。请记住,水平线存在是因为你在 HTML 页面中输入了"<br><hr/>",这添加了一个换行和一个水平规则或线。
这就是你可以将从 XML 文件中读取的内容与 C#结合起来,然后产生结果的方法。
章节回顾
本章的Default.aspx.cs文件的完整版本,包括注释,如下所示:
//using is a directive
//System is a name space
//name space is a collection of features that our needs to run
using System;
using System.Xml.Linq;//needed for XElement
//public means accessible anywhere
//partial means this class is split over multiple files
//class is a keyword and think of it as the outermost level of grouping
//:System.Web.UI.Page means our page inherits the features of a Page
public partial class _Default : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
//load XML file into "fromFile" variable
XElement fromFile = XElement.Load(@"C:\Users\towsi\Documents\Visual Studio 2015\WebSites\CSharpTemplateUpdated76143\XMLFile.xml" );
foreach(XElement childElement in fromFile.Elements())
{
//display value
sampLabel.Text += $"<br>Book Type:{childElement.Attribute("type").Value}";
//display author
sampLabel.Text += $"<br>{childElement.Element("author")}";
//display book title
sampLabel.Text += $"<br>{childElement.Element("booktitle")}";
//display price
sampLabel.Text += $"<br>{childElement.Element("price")}";
//adds horizontal rule across the page
sampLabel.Text += $"<br><hr/>";
}
}
}
总结
在本章中,你学习了 XML 的基础知识。你编写了 XML 代码,将生成的 XML 文件加载到程序中,遍历了 XML 文件的内容,并编写了显示结果的代码。
在下一章中,你将学习如何将 XML 写入文件,然后在记事本和 Internet Explorer 中查看结果。因此,你将遇到许多有用的小技巧。
第二十八章:使用 C#创建 XML 文件
在本章中,您将学习如何将 XML 写入文件,然后在记事本和 Internet Explorer 中查看结果。
向 HTML 添加按钮
启动一个项目,并在 HTML 页面中放置一个按钮。要做到这一点,转到视图|工具箱(Ctrl + Alt-X),在搜索字段中输入but,并将Button控件拖放到以<form id=...开头的行下面。更改按钮上的文本为保存文件。
接下来,转到设计视图。双击保存文件按钮。这会打开Default.aspx.cs中的事件处理程序。删除Page_Load存根。折叠using System;上下的所有注释—你不需要它们。该项目起始代码的相关部分应该看起来像图 28.2.1中的那样:
图 28.2.1:该项目的起始代码
添加命名空间
首先,让我们添加一些命名空间。在文件顶部附近的using System后面输入以下内容:
using System.Xml;
using System.Diagnostics;
您需要using System.Diagnostics;,这样您就可以在创建文件后立即在 Internet Explorer 和记事本中查看文件。
编码XmlWriter设置
接下来,您将设置XmlWriter设置。因此,在以protected void Button1_Click...开头的行下面的大括号之间输入以下内容:
XmlWriterSettings settings = new XmlWriterSettings();
在这一行中,您创建了该类的设置对象,然后设置了功能。接下来输入以下内容:
settings.Indent = true;
在此行下面输入以下内容:
settings.IndentChars = "\t";
在这里,"\t"是一个制表符。
写入硬盘
现在,因为XmlWriter类使用硬盘等,您需要将其包含在using语句中。因此,接下来输入以下内容:
using (XmlWriter writer = XmlWriter.Create(@"c:\data\sampfile2.xml", settings))
您将在硬盘上创建一个文件,c:\data\sampfile2.xml,然后将设置传递给要使用的设置。设置对象作为参数传递给XmlWriter内定义的Create函数。
在下一阶段,我们将实际写入,因此在大括号之间输入以下内容:
writer.WriteStartElement("bookstore");
writer.WriteEndElement();
在第二行,您立即关闭WriteStartElement方法。我们在这里添加一个结构。
现在,您将在这两行之间添加几行代码。首先编写一个属性字符串,如下所示:
writer.WriteAttributeString("name", "Tom's Book Store");
接下来,您将创建另一个元素。在这里,如果您缩进代码,将有所帮助,这表明book元素位于bookstore元素下面。为此,输入以下内容:
writer.WriteStartElement("book");
要写入的元素是book。接下来输入以下内容:
writer.WriteStartElement("bookauthor");
现在让我们做以下操作来关闭这个:
writer.WriteEndElement();
您这样做是为了保持结束和开始成对。
现在,在此处(在WriteEndElement行上方),您可以写入另一个元素。在这一行中,您将包括特定的书籍作者。同样,您将写入一个字符串,作者的名字将是值。输入以下内容:
writer.WriteString("John Smith");
在这里,要注意WriteAttribute与WriteString是不同的。WriteString在标签之间,而WriteAttribute给出属性,因此是不同的。这对我们的目的已经足够了。
格式化结果
现在,您希望确保结果看起来不错。因此,在最后一个WriteEndElement行下面的闭合大括号外面,输入以下内容:
Process.Start("notepad.exe", @"c:\data\sampfile2.xml");
您将在记事本中查看结果,然后需要文件的路径,因此从前面的using行中复制,c:\data\sampfile2.xml,并粘贴到此行中。
现在让我们再做一个。基本上,只需重复此行,并将其中的notepad.exe更改为iexplore.exe,如下所示,以指示接下来应该使用 Internet Explorer:
Process.Start("iexplore.exe", @"c:\data\sampfile2.xml");
运行程序
现在让我们在浏览器中打开并查看结果。单击保存文件按钮,您将看到在 Internet Explorer 中的样子:
图 28.2.2:在 Internet Explorer 中运行程序的结果
您可以看到它有结构,结果甚至是可折叠的,如 XML 标签之前的-符号所示,当然也是可展开的。书店的名称是汤姆的书店,这是属性,然后是约翰·史密斯,这是作为字符串写在书的作者标签或元素之间。
同样,在记事本中,它看起来像图 28.2.3中显示的屏幕,格式正确的 XML:
图 28.2.3:在记事本中运行程序的结果
所以,这些就是进行这些操作的基础知识。
章节回顾
本章的Default.aspx.cs文件的完整版本,包括注释,如下所示:
//using is a directive
//System is a name space
//name space is a collection of features that our needs to run
using System;
using System.Xml;
using System.Diagnostics;
//public means accessible anywhere
//partial means this class is split over multiple files
//class is a keyword and think of it as the outermost level of grouping
//:System.Web.UI.Page means our page inherits the features of a Page
public partial class _Default : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
//make a setting object
XmlWriterSettings settings = new XmlWriterSettings();
//set indent to true
settings.Indent = true;
//use tabs for indenting
settings.IndentChars = "\t";
//create file to write to
using (XmlWriter writer =
XmlWriter.Create(@"c:\data\sampfile2.xml", settings))
{
//outermost element
writer.WriteStartElement("bookstore");
//attribute of book store
writer.WriteAttributeString("name", "Tom's Book Store");
//new element called book
writer.WriteStartElement("book");
//new element called author
writer.WriteStartElement("bookauthor");
//this goes between the author tags
writer.WriteString("John Smith");
writer.WriteEndElement();
writer.WriteEndElement();
}
//priview the files in notepad and internet explorer
Process.Start("notepad.exe", @"c:\data\sampfile2.xml");
Process.Start("iexplore.exe", @"c:\data\sampfile2.xml");
}
}
总结
在本章中,您学会了如何将 XML 写入文件,然后在记事本和 Internet Explorer 中查看结果。您编写了XmlWriter设置,并编写了将结果写入硬盘并格式化结果的代码。
在下一章中,您将学习如何将 LINQ 和 XML 结合起来,使其更加实用。
第二十九章:使用 LINQ 查询 XML 文档
在本章中,您将学习如何将 LINQ 和 XML 结合起来,使其更加实用。
向 HTML 添加文本框和按钮
启动项目,并在内部,您需要做的第一件事是添加一个TextBox控件。要执行此操作,请转到视图|工具箱,在搜索字段中键入tex,然后将TextBox拖放到以<form id=...开头的行下面。在该行开头输入输入值:,使其看起来如下:
Enter Value:<asp:TextBoxID="TextBox1" runat="server"></asp:TextBox>
因此,您将有一个框;在框中输入一个值,然后您将获得一个结果。您将扫描 XML 文档以选择高于某个值的项目,例如60。这是我们的目标;换句话说,制作一个可搜索的页面。
接下来,您将在中插入一个按钮。因此,再次转到工具箱,在搜索字段中键入but,然后将Button控件拖放到前一行下面。更改Button控件上的文本,例如更改为搜索:
<asp:ButtonID="Button1" runat="server" Text="Search" />
接下来,转到设计视图。它看起来像图 29.3.1中显示的屏幕截图:
图 29.3.1: 设计视图中该项目的界面
双击搜索按钮。这将打开Default.aspx.cs文件。删除Page_Load存根。折叠using System;上下的所有注释—您不需要它们。该项目起始代码的相关部分应如图 29.3.2所示:
图 29.3.2: 该项目的起始代码
这里有一些有趣的代码—非常实用。请记住,无论您学习编程语言,现实生活中的挑战远比您在这本书中看到的任何内容都要困难得多。
添加命名空间
现在让我们添加一些命名空间。在文件顶部附近的using System下面输入以下内容:
using System.Xml.Linq;
using System.Linq;
因此,我们在 XML 和 LINQ 之间建立了一个桥梁—这是我们的目标。
清除输出
首先,您需要每次清除标签,以便输出不会在标签上累积。因此,在以protected void Button1_Click...开头的行下面的大括号之间输入以下内容:
sampLabel.Text = "";
构建元素树
接下来,我们将使用以下语法创建一个元素树:
XElement store = new XElement("store",
在这一行中,store是树的名称。基本上,它保存有关产品的信息。请记住,如果您想知道某物来自何处,只需将鼠标悬停在其上。因此,如果您将鼠标悬停在此行开头的XElement上,工具提示将显示它不是来自 XML 命名空间。相反,它来自 Xml.Linq 命名空间。
接下来,您将在store内放入其他元素。因此,在带有分号的括号关闭之前插入几行空行,现在您将在其中堆叠东西。
确保在前一行的store后面加上逗号。在键入逗号时,查看工具提示。您看到它说 params object[] content 吗?这意味着您可以指定要构建树的可变数量的参数。请记住,params 表示您可以指定可变数量的参数。
首先,我们将在 store 内部添加一个名为shoes的新元素。因此,缩进以下行:
new XElement("shoes",
接下来,进一步缩进以下行:
new XElement("brand", "Nike", new XAttribute("price", "65")),
在这里,您说new XAttribute,只是为了向您表明这是可能的。属性将是price,值将是,例如,$65。您关闭该属性并使用逗号关闭元素。
现在,由于您将重复此操作,请复制此行,并在下面粘贴它,将品牌名称更改为Stacy Adams,价格更改为$120,如下所示:
new XElement("brand", "Stacy Adams", new XAttribute("price", "120")),
让我们再重复一次。因此,再次复制此行,并将其粘贴在下面,将品牌名称更改为Florsheim,价格更改为$90,如下所示:
new XElement("brand", "Florsheim", new XAttribute("price", "90"))));
注意,在这里的最后一行,你用四个括号和一个分号结束。你必须非常小心。你必须确保一切匹配。所以,你有一个商店,然后你有一个鞋部门,在鞋部门内部你有不同的品牌:Nike、Stacy Adams 和 Florsheim。
保存商店 XML 文件
现在,最好能将这些写入文件,以确认结构被解释为预期的样子。所以在前面的XElement store...行下面输入以下内容,对齐缩进:
store.Save(@"c:\data\storefile.xml");
在这里,store.Save()是一个很好的函数,你可以直接调用它。你可以将它保存到一个文件中,比如:(@"c:\data \storefile.xml");。
测试程序
在做任何其他事情之前,让我们确认这将按预期工作,并且生成一个看起来不错的 XML 文件。所以,打开它在你的浏览器中,并点击搜索按钮,如图 29.3.3所示:
图 29.3.3:目前测试程序时显示的界面
当然,现在什么都没有显示,因为你还没有编写那部分代码。但是,如果你在c:\data目录下列出目录,就会看到保存的文件storefile.xml,如图 29.3.4所示:
图 29.3.4:文件 storefile.xml 保存在 c:\data 目录中
如果你在c:\data>提示符下键入notepad.exe storefile.xml,你将在记事本中看到图 29.3.5中显示的结果:
图 29.3.5:在记事本中打开的文件 storefile.xml
看起来很不错。你有一个store元素,然后在store元素内部有shoes,在shoes内部有品牌Nike、Stacy Adams和Florsheim,每双鞋的价格分别是:120 和$90。所以,这看起来是一个很好的文件,对我们的目的来说已经足够了。(在现实生活中,相信我,这些事情要复杂得多。)
搜索符合特定条件的项目
接着,在以store.Save...开头的行下面输入以下内容,以搜索鞋子:
var shoeSearch = from shoes in store.Descendants("shoes").Descendants("brand")
在这里,var shoeSearch是 LINQ 和 XML 的组合。
接下来,输入where (decimal),用于转换为十进制值,并且价格大于用户输入的值:
where (decimal)shoes.Attribute("price") >decimal.Parse(TextBox1.Text)
从符合搜索条件的项目中进行选择
一旦找到这些鞋子,你可以从中选择:
select shoes;
如果你将鼠标悬停在前面使用Descendants的第一次上面,它会告诉你它返回 IEnumerable。工具提示说它返回此文档或元素的后代元素的过滤集合,按文档顺序排列。
另外,如果你将鼠标悬停在第二次使用Descendants上,你会看到它是按品牌进行的。一旦你到达那个级别,你可以,例如,将鼠标悬停在前面以where...开头的行中的price属性上,然后将这个属性与用户指定的值进行比较。所以,就好像你从外部到内部遍历,直到你到达价格属性,然后在那个阶段,你将该值与用户输入的值进行比较。
显示结果
接下来输入以下行,以显示搜索选择的所有鞋子品牌和价格:
foreach(XElement shoeBrand in shoeSearch)
最后,在前面的行下面的一对大括号之间输入以下内容:
sampLabel.Text += $"<br>Brand:{shoeBrand}<br>Price:{(decimal)shoeBrand.Attribute("price"):C}";
在这一行中,可能有多个值,所以你要追加。请注意,我们使用<br>标签将每个结果推到下一行。要显示价格,你要说(decimal)来转换为十进制值,然后在shoeBrand.Attribute("price")之后,你用:C将其转换为货币格式。这就是所有的代码。将所有这些都打出来非常重要。学习的最佳方式是通过实践,而不仅仅是打开一个事先准备好的文件并运行它。
运行程序
现在再次打开浏览器,输入一个值,比如45,然后点击搜索按钮。它应该返回所有的鞋子,因为价格都高于这个值,如图 29.3.6所示:
图 29.3.6:显示所有鞋子和价格,因为输入的值小于任何鞋子的价格
现在输入100作为值,然后再次点击搜索按钮。在这种情况下,它只返回价格为 120 美元的 Stacy Adams 鞋子,如图 29.3.7所示:
图 29.3.7:只返回 Stacy Adams 鞋子,因为它的价格超过 100 美元
让我们再做一个。再输入85,然后再次点击搜索按钮。如图 29.3.8所示,它返回 Stacy Adams 和 Florsheim 鞋子,因为这两者的价格都在 85 美元或以上:
图 29.3.8:返回 Stacy Adams 和 Florsheim 鞋子,因为两者的价格都在 85 美元或以上
就是这样。一切都按预期运行。我们还使用了你编写的整个XElement构造来生成了一个漂亮的 XML 文件,以便这个程序能够正确运行。
章节回顾
本章的Default.aspx.cs文件的完整版本,包括注释,如下所示:
//using is a directive
//System is a name space
//name space is a collection of features that our needs to run
using System;
using System.Xml.Linq;
using System.Linq;
//public means accessible anywhere
//partial means this class is split over multiple files
//class is a keyword and think of it as the outermost level of grouping
//:System.Web.UI.Page means our page inherits the features of a Page
public partial class _Default : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
//clear label on every button click so stuff does not accumulate
sampLabel.Text = "";
//create a nice XML tree structure for searching: store is the
//root, inside that is shoes,
//and then under shoes are three different brands
XElement store = new XElement("store",
new XElement("shoes",
new XElement("brand","Nike",
new XAttribute("price","65")),
new XElement("brand", "Stacy Adams",
new XAttribute("price","120")),
new XElement("brand", "Florsheim",
new XAttribute("price","90"))));
//save file to drive to confirm it looks like healthy XML
store.Save(@"c:\data\storefile.xml");
//search down to the level of the price attribute, and compare that
//value against the value entered in the search box by the user
var shoeSearch = from shoes in store.Descendants("shoes").Descendants("brand")
where (decimal)shoes.Attribute("price") > decimal.Parse(TextBox1.Text)select shoes;
//display all the shoe brands, and the prices
foreach(XElement shoeBrand in shoeSearch)
{
sampLabel.Text += $"<br>Brand:{shoeBrand}<br>Price:{(decimal)shoeBrand.Attribute("price"):C}";
}
}
}
总结
在本章中,你学会了如何结合 LINQ 和 XML 来做一些更实际的事情。你构建了一个元素树,并编写了代码来保存商店的 XML 文件,搜索符合特定条件的项目,并从找到的项目中选择符合搜索条件的项目。