Chapter 9: Using XML and Web Services


Various chapters of this book have mentioned Extensible Markup Language (XML) documents and their ability to represent structured data in a flat file. This chapter looks closer at XML and explains why the technology is important to the extended enterprise. Then, building from your understanding of XML, this chapter introduces the concept of Web services and the components that make up Web services. This chapter continues to expand the IssueTracker application by building out the Web service layer of the IssueTracker application to produce a Web service integration platform for any Web-enabled application to use.

Understanding the Extensible Markup Language

As described in Chapter 6, "Automating Business Processes," XML is a flexible language used to create documents that share formatting and data for document exchange over the Web. A business document written in XML can be viewed and edited with any text editor and is usually easy to read. XML usage is most prominent with businesses that exchange documents in an environment where neither side wants to depend on the technology the other side is using.

Reviewing the Evolution of XML

The primary purpose of XML is to deliver structured data. Sources of structured data can include spreadsheets, business functions, and databases. Overall, XML is a set of rules for designing textual representations of structured data. XML is not a programming language, and it does not require a programmer to interact with it. It is extensible and platform independent, and it supports internationalization and localization.

XML looks much like Hypertext Markup Language (HTML) in that it is organized into tags (words bracketed by < and >) and attributes. Although HTML specifies what each tag and attribute means and how the text between the tags is formatted in a browser, XML uses the tags to identify blocks of data and their relationships, leaving the interpretation of the data to the application that reads it.

Although XML is text, it is not intended to be read by people. Data sources, such as spreadsheets, business functions, and databases, often store that data on disk, usually using a binary format. One advantage of a text format is that it allows people, if necessary, to look at the data without the program that produced it. Text formats also allow developers to more easily debug applications. Like HTML, XML files are text files that people should not have to read but could if necessary.

Before the emergence of XML, there was Standard Generalized Markup Language (SGML), which was developed in the early 1980s. SGML has been a standard since 1986, and it is widely used for large documentation projects. The development of HTML started in 1990. The development of XML started in 1996 and has been a World Wide Web Consortium (W3C) recommendation since February 1998. The designers of XML took the best parts of SGML, guided by the experience with HTML, and produced something that is as powerful as SGML but much easier to use. Whereas SGML is mostly used for technical documentation rather than other kinds of data, XML is the opposite .

XML is license free, platform independent and widely supported. Choosing XML as the basis for a project gives you access to a large and growing number of tools, applications, and developers.

Resolving Conflicts with XML Namespaces

XML namespaces clearly identify elements within an XML document that would otherwise lead to ambiguity. For example, if an XML document containing Issue information merges with another document containing User information, certain elements within the resulting document may experience a name collision, as demonstrated in Listing 9-1.

Listing 9-1: issuedata.xml
start example
 <Dat_Issue>     <IssueID>  1  </IssueID>     <TypeID>  1  </TypeID>     <EntryDate>  2002-08-15T00:00:00.0000000-07:00  </EntryDate>     <StatusID>  1  </StatusID>     <Summary>  Unable to print  </Summary>  <Description>I can not print any PowerPoint files on the //MKT-GROUP   printer in the lobby.</Description>  <PriorityID>1</PriorityID>     <User>         <Firstname>  Larry  </Firstname>         <Lastname>  Dalton  </Lastname>  <Description>Marketing Director</Description>  <EmailAddress>  larryd@sample.com  </EmailAddress>         <UserType>  1  </UserType>     </User> </Dat_Issue> 
end example
 

The problem appears when an XML document uses a <Description> tag to describe an Issue and later to describe a User. An application has no way of knowing how to process the <Description> tag differently unless it has some additional information outside of the document.

Namespaces address this problem by extending the data model to fully qualify element and attribute names. The purpose of a qualified name is to allow applications to more clearly identify a tag or attribute name. You construct qualified names with a prefix, a colon , and a local name. The prefix identifies a specific Uniform Resource Identifier (URI) as defined in RFC 2396. The local name specifies any identifier used locally within the document:

 qualified_name = <namespace_identifier : local_name> 

Namespaces remove ambiguity from XML documents just as class name-spaces do in the C# language. Including namespaces in XML documents occur in two separate steps, the namespace reference and the namespace usage. Listing 9-2 replaces all local tag names with qualified tag names.

Listing 9-2: issuedata.qualified.xml
start example
 <Dat_Issue     xmlns:issue="http://www.enterprisedotnet/xml/issue"     xmlns:user="http://www.enterprisedotnet/xml/user">     <issue:IssueID>  1  </issue:IssueID>     <issue:TypeID>  1  </issue:TypeID>     <issue:EntryDate>  2002-08-15T00:00:00.0000000-07:00  </issue:EntryDate>     <issue:StatusID>  1  </issue:StatusID>     <issue:Summary>  Unable to print  </issue:Summary>  <  issue:  Description>I can not print any PowerPoint files on the //MKT-GROUP   printer in the lobby.</  issue:  Description>  <issue:PriorityID>  1  </issue:PriorityID>     <user:User>          <user:Firstname>  Larry  </user:Firstname>          <user:Lastname>  Dalton  </user:Lastname>  <  user:  Description>Marketing Director</  user:  Description>  <user:EmailAddress>  larryd@sample.com  </user:EmailAddress>          <user:UserType>  1  </user:UserType>     </user:User> </issue:Dat_Issue> 
end example
 

In this case, the elements prefixed with issue: are associated with a name-space that has a URI of http://www.enterprisedotnet/xml/issue , and those prefixed with user: are associated with a namespace that has a URI of http://www.enterprisedotnet/xml/user .

The namespace prefixes map to the complete namespace URI as attributes of the first element. Because XML namespaces significantly increase the size of the document and make the text more difficult to read, documents may define a single default namespace. Listing 9-3 demonstrates using a default namespace.

Listing 9-3: issuedata.default.xml
start example
 <Dat_Issue     xmlns="http://www.enterprisedotnet/xml/issue"     xmlns:user="http://www.enterprisedotnet/xml/user">     <IssueID>  1  </IssueID>     <TypeID>  1  </TypeID>     <EntryDate>  2002-08-15T00:00:00.0000000-07:00  </EntryDate>     <StatusID>  1  </StatusID>     <Summary>  Unable to print  </Summary>  <Description>I can not print any PowerPoint files on the //MKT-GROUP   printer in the lobby.</Description>  <PriorityID>  1  </PriorityID>  <user:User>   <user:Firstname>Larry</user:Firstname>   <user:Lastname>Dalton</user:Lastname>   <user:Description>Marketing Director</user:Description>   <user:EmailAddress>larryd@sample.com</user:EmailAddress>   <user:UserType>1</user:UserType>   </user:User>  </Dat_Issue> 
end example
 

In this case, a prefix maps to the User namespace but not the Issue name-space. Therefore, all of the local element and attribute names will use the Issue namespace by default and not require the issue: prefix. The result is a much smaller and easier-to-read XML document.

Enforcing Structure with XML Schemas

An XML schema , also referred to as an XML Schema Definition (XSD) , describes the structure and rules for processing XML documents. Its purpose is to define the working elements of an XML document and to define the elements and attributes that can appear within a document. This enables the XML parser to determine if the document is valid or invalid, as illustrated in Figure 9-1.

click to expand
Figure 9-1: The XML document validation process

The schema also defines how many child elements exist, which elements are child elements, and in which order the child elements must appear. Finally, a schema defines whether an element is empty or can include text, which data types are expected for each element, and their default values. Listing 9-4 summarizes the IssueTracker DataSet schema.

Listing 9-4: DataSetIssueTracker.xsd (Partial Listing)
start example
 <?xml version="1.0" encoding="UTF-8" ?> <xs:schema id="DataSetIssueTracker"     xmlns="http://www.tempuri.org/DataSetIssueTracker.xsd"     xmlns:xs="http://www.w3.org/2001/XMLSchema"     targetNamespace="http://www.tempuri.org/DataSetIssueTracker.xsd"     attributeFormDefault="qualified"     elementFormDefault="qualified">     <xs:element name="DataSetIssueTracker">     <xs:complexType>     <xs:choice maxOccurs="unbounded">     <xs:element name="Dat_Issue">         <xs:complexType>             <xs:sequence>                 <xs:element name="IssueID" type="xs:long" />                 <xs:element name="TypeID" type="xs:int" minOccurs="0" />                 <xs:element name="UserID" type="xs:long" minOccurs="0" />                 <xs:element name="EntryDate" type="xs:dateTime" minOccurs="0" />                 <xs:element name="StatusID" type="xs:int" minOccurs="0" />                 <xs:element name="Summary" type="xs:string" minOccurs="0" />                 <xs:element name="Description" type="xs:string" minOccurs="0" />                 <xs:element name="PriorityID" type="xs:int" minOccurs="0" />             </xs:sequence>         </xs:complexType>     </xs:element>     <xs:element name="Dat_User">         <xs:complexType>             <xs:sequence>                 <xs:element name="UserID" type="xs:long" />                 <xs:element name="Password" type="xs:string" minOccurs="0" />                 <xs:element name="Firstname" type="xs:string" minOccurs="0" />                 <xs:element name="Lastname" type="xs:string" minOccurs="0" />                 <xs:element name="EmailAddress" type="xs:string" minOccurs="0" />                 <xs:element name="UserType" type="xs:int" minOccurs="0" />                 <xs:element name="CreateDate" type="xs:dateTime" minOccurs="0" />             </xs:sequence>         </xs:complexType>     </xs:element>     </xs:choice>     </xs:complexType>     <xs:unique name="Dat_Issue_Constraint" msdata:ConstraintName="Constraint1"         msdata:PrimaryKey="true">         <xs:selector xpath=".//mstns:Dat_Issue" />         <xs:field xpath="mstns:IssueID" />     </xs:unique>     <xs:unique name="Dat_User_Constraint" msdata:ConstraintName="Constraint"         msdata:PrimaryKey="true">         <xs:selector xpath=".//mstns:Dat_User" />         <xs:field xpath="mstns:UserID" />     </xs:unique>     </xs:element> </xs:schema> 
end example
 
Note  

By default, new XML documents have a default namespace set to http://www.tempuri.org/ . See the "Changing the Default Namespace" section later within this chapter to learn how to modify this setting.

The most noticeable characteristic of the XSD in Listing 9-4 is that all tags have an xs: prefix. This prefix maps to the XML schema namespace at http://www.w3.org/2001/XMLSchema . This listing outlines the valid data values, field types, constraints, and relationships for the Dat_Issue and Dat_User data tables contained within the application's DataSet object.

Expressing DataSets in XML

As described in Chapter 2, "Accessing Data in ADO.NET," the DataSet class is useful for managing large amounts of data pulled from the database. This inmemory representation of the database includes representations of tables, table relationships, and field constraints. The DataSet is also capable of reading and writing its data and schema to XML. You fill DataSets from XML using the ReadXml method, and they output XML with the WriteXml method. Listing 9-5 implements a possible data export method for the Business Facade project that writes the contents of a filled DataSet to a specified file or a returned string.

Listing 9-5: Exporting XML Data from the ReferenceDataSet Object
start example
 public string ExportDataToXml( string strFilename ) {     string strXmlData = "";     try     {          //check to see if filename is valid          if( strFilename != null && strFilename.Length > 0 )          {              System.IO.StreamWriter streamWrite =                  new System.IO.StreamWriter( strFilename );              _AppDataComponent.ReferenceDataSet.WriteXml( streamWrite,                  XmlWriteMode.WriteSchema );              streamWrite.Close();          }          else          {              //return xml output as a string              strXmlData = _AppDataComponent.ReferenceDataSet.GetXml();          }     }     catch( Exception x )     {         EventLog systemLog = new EventLog();         systemLog.Source = "IssueTracker";         systemLog.WriteEntry( x.Message, EventLogEntryType.Error, 0 );     }     return strXmlData; } 
end example
 

In this method, a string parameter provides the export method a value that represents an export filename. If the filename is valid, then the code creates and initializes a new StreamWriter object with the export filename. Next, the WriteXml method attached to the ReferenceDataSet object generates an XML representation of itself and writes it to the specified stream writer. If the filename is not valid, then the code creates and returns only a string representation of the ReferenceDataSet object. You might use the string representation of the DataSet's XML data for exchanging information between Web services.

In addition to producing XML, a DataSet object is also capable of reading XML as a data source. It can read XML content from a string parameter, an input stream, or a path to an XML file. Listing 9-6 presents an import method that takes XML data and populates the ReferenceDataSet object.

Listing 9-6: Importing XML Data into the ReferenceDataSet Object
start example
 public void ImportDataFromXml( string strXmlData, string strFilename ) {     try     {          if( strFilename != null && strFilename.Length > 0 )          {              //pull xml from file              System.IO.StringReader streamRead = new System.IO.StringReader(                  strFilename );              _AppDataComponent.ReferenceDataSet.ReadXml( streamRead,                  XmlReadMode.ReadSchema );          }          else          {              //pull xml from string argument             System.IO.StringReader readerXml = new System.IO.StringReader(                 strXmlData );             _AppDataComponent.ReferenceDataSet.ReadXml( readerXml,                 XmlReadMode.IgnoreSchema );          }     }     catch( Exception x )     {         EventLog systemLog = new EventLog();         systemLog.Source = "IssueTracker";         systemLog.WriteEntry( x.Message, EventLogEntryType.Error, 0 );     }     return; } 
end example
 

This method passes two arguments to point the way to XML data. The first parameter is a string object containing the actual XML data. The second parameter is a string that represents a filename where the XML data is stored. If the filename is valid, it extracts the XML data from the file. The code creates and initializes a new StringReader object with the supplied filename. Next, the ReadXml method attached to the ReferenceDataSet object pulls the XML data from the file with the help of the string reader. If the filename is not valid, then the ReadXml method uses the string reader to pull the XML data from the string argument. This approach supports interaction with desktop applications that can access the local file system and Web services capable of only exchanging data represented by string objects.

Note  

If a DataSet object already contains data, the new XML data is added to the existing DataSet. The ReadXml method does not merge XML data that has matching primary keys. To overwrite an existing row, you must use the ReadXml method to create a new DataSet. Then, the new DataSet merges with the existing DataSet.

Listings 9-5 and 9-6 use two important methods that the DataSet class provides for reading and writing data to and from XML. Table 9-1 outlines all the methods that the DataSet object provides for interacting with XML as well as schema data.

Table 9-1: XML-Related Methods Provided by the DataSet Object

METHOD

DESCRIPTION

GetXml

Returns a string containing an XML representation of the data in the DataSet object.

GetXmlSchema

Returns a string containing the XSD for the XML returned by the GetXml method.

WriteXml

Writes the XML representation of the data in the DataSet object to a Stream object, a file, a TextWriter object, or an XmlWriter object. This XML can either include or omit the corresponding XSD.

WriteXmlSchema

Writes the XSD for the DataSet to a Stream object, a file, a TextWriter object, or an XmlWriter object.

ReadXml

Reads the XML written by the WriteXml method.

ReadXmlSchema

Reads the XSD written by the WriteXmlSchema method.




Developing. NET Enterprise Applications
Developing .NET Enterprise Applications
ISBN: 1590590465
EAN: 2147483647
Year: 2005
Pages: 119

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net