Apress-Visual CSharp 2010 Recipes A Problem Solution Approach_2 potx

95 557 0
Apress-Visual CSharp 2010 Recipes A Problem Solution Approach_2 potx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

C H A P T E R 6 ■ ■ ■ 261 XML Processing One of the most remarkable aspects of the Microsoft .NET Framework is its deep integration with XML. In many .NET applications, you won’t even be aware you’re using XML technologies—they’ll just be used behind the scenes when you serialize a Microsoft ADO.NET DataSet, call a web service, or read application settings from a Web.config configuration file. In other cases, you’ll want to work directly with the System.Xml namespaces to manipulate Extensible Markup Language (XML) data. Common XML tasks don’t just include parsing an XML file, but also include validating it against a schema, applying an Extensible Stylesheet Language (XSL) transform to create a new document or Hypertext Markup Language (HTML) page, and searching intelligently with XPath. In .NET 3.5, Microsoft added LINQ to XML, which integrates XML handling into the LINQ model for querying data sources. You can use the same keywords and syntax to query XML as you would a collection or a database. The recipes in this chapter describe how to do the following: • Read, parse, and manipulate XML data (recipes 6-1, 6-2, 6-3, and 6-7) • Search an XML document for specific nodes, either by name (recipe 6-4), by namespace (recipe 6-5), or by using XPath (recipe 6-6) • Validate an XML document with an XML schema (recipe 6-8) • Serialize an object to XML (recipe 6-9), create an XML schema for a class (recipe 6- 10), and generate the source code for a class based on an XML schema (recipe 6- 11) • Transform an XML document to another document using an XSL Transformations (XSLT) stylesheet (recipe 6-12) • Use LINQ to XML to load, create, query and modify XML trees (recipes 6-13, 6-14, 6-15, and 6-16). 6-1. Show the Structure of an XML Document in a TreeView Problem You need to display the structure and content of an XML document in a Windows-based application. CHAPTER 6 ■ XML PROCESSING 262 Solution Load the XML document using the System.Xml.XmlDocument class. Create a reentrant method that converts a single XmlNode into a System.Windows.Forms.TreeNode, and call it recursively to walk through the entire document. How It Works The .NET Framework provides several different ways to process XML documents. The one you use depends in part upon your programming task. One of the most fully featured classes is XmlDocument, which provides an in-memory representation of an XML document that conforms to the W3C Document Object Model (DOM). The XmlDocument class allows you to browse through the nodes in any direction, insert and remove nodes, and change the structure on the fly. For details of the DOM specification, go to www.w3c.org. ■ Note The XmlDocument class is not scalable for very large XML documents, because it holds the entire XML content in memory at once. If you want a more memory-efficient alternative, and you can afford to read and process the XML piece by piece, consider the XmlReader and XmlWriter classes described in recipe 6-7. To use the XmlDocument class, simply create a new instance of the class and call the Load method with a file name, a Stream, a TextReader, or an XmlReader object. It is also possible to read the XML from a simple string with the LoadXML method. You can even supply a string with a URL that points to an XML document on the Web using the Load method. The XmlDocument instance will be populated with the tree of elements, or nodes, from the source document. The entry point for accessing these nodes is the root element, which is provided through the XmlDocument.DocumentElement property. DocumentElement is an XmlElement object that can contain one or more nested XmlNode objects, which in turn can contain more XmlNode objects, and so on. An XmlNode is the basic ingredient of an XML file. Common XML nodes include elements, attributes, comments, and contained text. When dealing with an XmlNode or a class that derives from it (such as XmlElement or XmlAttribute), you can use the following basic properties: • ChildNodes is an XmlNodeList collection that contains the first level of nested nodes. • Name is the name of the node. • NodeType returns a member of the System.Xml.XmlNodeType enumeration that indicates the type of the node (element, attribute, text, and so on). • Value is the content of the node, if it’s a text or CDATA node. • Attributes provides a collection of node objects representing the attributes applied to the element. • InnerText retrieves a string with the concatenated value of the node and all nested nodes. CHAPTER 6 ■ XML PROCESSING 263 • InnerXml retrieves a string with the concatenated XML markup for all nested nodes. • OuterXml retrieves a string with the concatenated XML markup for the current node and all nested nodes. The Code The following example walks through every element of an XmlDocument using the ChildNodes property and a recursive method. Each node is displayed in a TreeView control, with descriptive text that either identifies it or shows its content. using System; using System.Windows.Forms; using System.Xml; using System.IO; namespace Apress.VisualCSharpRecipes.Chapter06 { public partial class Recipe06_01 : System.Windows.Forms.Form { public Recipe06_01() { InitializeComponent(); } // Default the file name to the sample document. private void Recipe06_01_Load(object sender, EventArgs e) { txtXmlFile.Text = Path.Combine(Application.StartupPath, @" \ \ProductCatalog.xml"); } private void cmdLoad_Click(object sender, System.EventArgs e) { // Clear the tree. treeXml.Nodes.Clear(); // Load the XML document. XmlDocument doc = new XmlDocument(); try { doc.Load(txtXmlFile.Text); } catch (Exception err) { MessageBox.Show(err.Message); return; } CHAPTER 6 ■ XML PROCESSING 264 // Populate the TreeView. ConvertXmlNodeToTreeNode(doc, treeXml.Nodes); // Expand all nodes. treeXml.Nodes[0].ExpandAll(); } private void ConvertXmlNodeToTreeNode(XmlNode xmlNode, TreeNodeCollection treeNodes) { // Add a TreeNode node that represents this XmlNode. TreeNode newTreeNode = treeNodes.Add(xmlNode.Name); // Customize the TreeNode text based on the XmlNode // type and content. switch (xmlNode.NodeType) { case XmlNodeType.ProcessingInstruction: case XmlNodeType.XmlDeclaration: newTreeNode.Text = "<?" + xmlNode.Name + " " + xmlNode.Value + "?>"; break; case XmlNodeType.Element: newTreeNode.Text = "<" + xmlNode.Name + ">"; break; case XmlNodeType.Attribute: newTreeNode.Text = "ATTRIBUTE: " + xmlNode.Name; break; case XmlNodeType.Text: case XmlNodeType.CDATA: newTreeNode.Text = xmlNode.Value; break; case XmlNodeType.Comment: newTreeNode.Text = "<! " + xmlNode.Value + " >"; break; } // Call this routine recursively for each attribute. // (XmlAttribute is a subclass of XmlNode.) if (xmlNode.Attributes != null) { foreach (XmlAttribute attribute in xmlNode.Attributes) { ConvertXmlNodeToTreeNode(attribute, newTreeNode.Nodes); } } CHAPTER 6 ■ XML PROCESSING 265 // Call this routine recursively for each child node. // Typically, this child node represents a nested element // or element content. foreach (XmlNode childNode in xmlNode.ChildNodes) { ConvertXmlNodeToTreeNode(childNode, newTreeNode.Nodes); } } } } Usage As an example, consider the following simple XML file (which is included with the sample code as the ProductCatalog.xml file): <?xml version="1.0" ?> <! This document is a sample catalog for demonstration purposes > <productCatalog> <catalogName>Freeman and Freeman Unique Catalog 2010</catalogName> <expiryDate>2012-01-01</expiryDate> <products> <product id="1001"> <productName>Gourmet Coffee</productName> <description>Beans from rare Chillean plantations.</description> <productPrice>0.99</productPrice> <inStock>true</inStock> </product> <product id="1002"> <productName>Blue China Tea Pot</productName> <description>A trendy update for tea drinkers.</description> <productPrice>102.99</productPrice> <inStock>true</inStock> </product> </products> </productCatalog> Figure 6-1 shows how this file will be rendered in the Recipe06_01 form. CHAPTER 6 ■ XML PROCESSING 266 Figure 6-1. The displayed structure of an XML document 6-2. Insert Nodes in an XML Document Problem You need to modify an XML document by inserting new data, or you want to create an entirely new XML document in memory. Solution Create the node using the appropriate XmlDocument method (such as CreateElement, CreateAttribute, CreateNode, and so on). Then insert it using the appropriate XmlNode method (such as InsertAfter, InsertBefore, or AppendChild). How It Works Inserting a node into the XmlDocument class is a two-step process. You must first create the node, and then you insert it at the appropriate location. You can then call XmlDocument.Save to persist changes. CHAPTER 6 ■ XML PROCESSING 267 To create a node, you use one of the XmlDocument methods starting with the word Create, depending on the type of node. This ensures that the node will have the same namespace as the rest of the document. (Alternatively, you can supply a namespace as an additional string argument.) Next, you must find a suitable related node and use one of its insertion methods to add the new node to the tree. The Code The following example demonstrates this technique by programmatically creating a new XML document: using System; using System.Xml; namespace Apress.VisualCSharpRecipes.Chapter06 { public class Recipe06_02 { private static void Main() { // Create a new, empty document. XmlDocument doc = new XmlDocument(); XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null); doc.AppendChild(docNode); // Create and insert a new element. XmlNode productsNode = doc.CreateElement("products"); doc.AppendChild(productsNode); // Create a nested element (with an attribute). XmlNode productNode = doc.CreateElement("product"); XmlAttribute productAttribute = doc.CreateAttribute("id"); productAttribute.Value = "1001"; productNode.Attributes.Append(productAttribute); productsNode.AppendChild(productNode); // Create and add the subelements for this product node // (with contained text data). XmlNode nameNode = doc.CreateElement("productName"); nameNode.AppendChild(doc.CreateTextNode("Gourmet Coffee")); productNode.AppendChild(nameNode); XmlNode priceNode = doc.CreateElement("productPrice"); priceNode.AppendChild(doc.CreateTextNode("0.99")); productNode.AppendChild(priceNode); // Create and add another product node. productNode = doc.CreateElement("product"); productAttribute = doc.CreateAttribute("id"); productAttribute.Value = "1002"; productNode.Attributes.Append(productAttribute); productsNode.AppendChild(productNode); CHAPTER 6 ■ XML PROCESSING 268 nameNode = doc.CreateElement("productName"); nameNode.AppendChild(doc.CreateTextNode("Blue China Tea Pot")); productNode.AppendChild(nameNode); priceNode = doc.CreateElement("productPrice"); priceNode.AppendChild(doc.CreateTextNode("102.99")); productNode.AppendChild(priceNode); // Save the document (to the console window rather than a file). doc.Save(Console.Out); Console.ReadLine(); } } } When you run this code, the generated XML document looks like this: <?xml version="1.0"?> <products> <product id="1001"> <productName>Gourmet Coffee</productName> <productPrice>0.99</productPrice> </product> <product id="1002"> <productName>Blue China Tea Pot</productName> <productPrice>102.99</productPrice> </product> </products> 6-3. Quickly Append Nodes in an XML Document Problem You need to add nodes to an XML document without requiring lengthy, verbose code. CHAPTER 6 ■ XML PROCESSING 269 Solution Create a helper function that accepts a tag name and content, and can generate the entire element at once. Alternatively, use the XmlDocument.CloneNode method to copy branches of an XmlDocument. How It Works Inserting a single element into an XmlDocument requires several lines of code. You can shorten this code in several ways. One approach is to create a dedicated helper class with higher-level methods for adding elements and attributes. For example, you could create an AddElement method that generates a new element, inserts it, and adds any contained text—the three operations needed to insert most elements. The Code Here’s an example of one such helper class: using System; using System.Xml; namespace Apress.VisualCSharpRecipes.Chapter06 { public class XmlHelper { public static XmlNode AddElement(string tagName, string textContent, XmlNode parent) { XmlNode node = parent.OwnerDocument.CreateElement(tagName); parent.AppendChild(node); if (textContent != null) { XmlNode content; content = parent.OwnerDocument.CreateTextNode(textContent); node.AppendChild(content); } return node; } public static XmlNode AddAttribute(string attributeName, string textContent, XmlNode parent) { XmlAttribute attribute; attribute = parent.OwnerDocument.CreateAttribute(attributeName); attribute.Value = textContent; parent.Attributes.Append(attribute); [...]... truncated] Validation error: The 'productPrice' element has an invalid value according to 285 CHAPTER 6 ■ XML PROCESSING its data type [path information truncated] Validation error: The 'inStock' element has an invalid value according to its data type [path information truncated] Validation failed Finally, if you want to validate an XML document and load it into an in-memory XmlDocument, you need to take... Problem You need to read XML from a stream or write it to a stream However, you want to process the information one node at a time, rather than loading it all into memory with an XmlDocument Solution To write XML, create an XmlWriter that wraps a stream and use Write methods (such as WriteStartElement and WriteEndElement) To read XML, create an XmlReader that wraps a stream, and call Read to move from node... argument Additionally, supply an asterisk (*) for the element name if you want to match all tags How It Works Many XML documents contain nodes from more than one namespace For example, an XML document that represents a scientific article might use a separate type of markup for denoting math equations and vector diagrams, or an XML document with information about a purchase order might aggregate client and... false.) 6-8 Validate an XML Document Against a Schema Problem You need to validate the content of an XML document by ensuring that it conforms to an XML schema Solution When you call XmlReader.Create, supply an XmlReaderSettings object that indicates you want to perform validation Then move through the document one node at a time by calling XmlReader.Read, catching any validation exceptions To find all the... XmlSchemaSet(); settings.Schemas = schemas; // When loading the schema, specify the namespace it validates // and the location of the file Use null to use 283 CHAPTER 6 ■ XML PROCESSING // the targetNamespace value from the schema schemas.Add(null, schemaFilename); // Specify an event handler for validation errors settings.ValidationEventHandler += ValidationEventHandler; // Create the validating reader... XmlWriter and XmlReader classes read or write XML directly from a stream one node at a time These classes do not provide the same features for navigating and manipulating your XML as XmlDocument, but they do provide higher performance and a smaller memory footprint, particularly if you need to deal with large XML documents Both XmlWriter and XmlReader are abstract classes, which means you cannot create an... and processing will be aborted The Code The next example shows a utility class that displays all errors in an XML document when the ValidateXml method is called Errors are displayed in a console window, and a final Boolean variable is returned to indicate the success or failure of the entire validation operation using System; using System.Xml; using System.Xml.Schema; namespace Apress.VisualCSharpRecipes.Chapter06... creating the new object during deserialization • All class properties must be readable and writable This is because XmlSerializer uses the property get accessor to retrieve information and the property set accessor to restore the data after deserialization ■ Note You can also store your objects in an XML-based format using NET serialization and System.Runtime Serialization.Formatters.Soap.SoapFormatter... an attribute of type ID, you can also use a method called GetElementById to retrieve an element that has a matching ID value 6-5 Get XML Nodes in a Specific XML Namespace Problem You need to retrieve nodes from a specific namespace using an XmlDocument 272 CHAPTER 6 ■ XML PROCESSING Solution Use the overload of the XmlDocument.GetElementsByTagName method that requires a namespace name as a string argument... product catalog first shown in recipe 6-1 You can represent this XML document using ProductCatalog and Product objects Here’s the class code that you might use: using System; using System.Xml.Serialization; namespace Apress.VisualCSharpRecipes.Chapter06 { [XmlRoot("productCatalog")] public class ProductCatalog { [XmlElement("catalogName")] public string CatalogName; // Use the date data type (and ignore . document is a sample catalog for demonstration purposes > <productCatalog> <catalogName>Freeman and Freeman Unique Catalog 20 10& lt;/catalogName> <expiryDate> ;20 12- 01-01</expiryDate>. file, but also include validating it against a schema, applying an Extensible Stylesheet Language (XSL) transform to create a new document or Hypertext Markup Language (HTML) page, and searching. XmlDocument.GetElementsByTagName method that requires a namespace name. You can use this method to find tags by name or to find all the tags in the specified namespace if you supply an asterisk for the tag name parameter.

Ngày đăng: 18/06/2014, 16:20

Từ khóa liên quan

Mục lục

  • Prelim

  • Contents at a Glance

  • Contents

  • About the Authors

  • About the Technical Reviewer

  • Acknowledgments

  • Introduction

  • Application Development

    • 1-1. Create a Console Application from the Command Line

      • Problem

      • Solution

      • How It Works

      • The Code

      • Usage

      • 1-2. Create a Windows-Based Application from the Command Line

        • Problem

        • Solution

        • How It Works

        • The Code

        • Usage

        • 1-3. Create and Use a Code Module

          • Problem

          • Solution

          • How It Works

Tài liệu cùng người dùng

Tài liệu liên quan