C-7-入门实用指南-四-

107 阅读7分钟

C#7 入门实用指南(四)

原文:zh.annas-archive.org/md5/0D2F44FACA4630D8785DF55498F3E611

译者:飞龙

协议:CC BY-NC-SA 4.0

第二十七章:创建和使用 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");

在这里,要注意WriteAttributeWriteString是不同的。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 文档以选择高于某个值的项目,例如5050 或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内部有品牌NikeStacy AdamsFlorsheim,每双鞋的价格分别是:6565、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 文件,搜索符合特定条件的项目,并从找到的项目中选择符合搜索条件的项目。