Figure 10-11 SQL Server 2005 and the XML Data Type You’ve seen that retrieving data from SQL Server 2000 is straightforward, if a little limited.. SQL Server 2005 can now have a table wi
Trang 1}
}
Response.ContentType = "text/xml";
x.Save(Response.Output);
This code creates anXmlDocumentcalledCustomers Then it executes the SQL command and retrieves
the XML data into anXmlReader AnXPathNavigatoris created from theXmlDocument, and a child
node is prepended to the document A single call to theWriteNodemethod of theXmlWriterretrieved
from theXPathDocumentmoves the entire XML fragment into the well-formedXmlDocument Because
the SQL statement containedfrom Customers as Customeras a table alias, each XML element is named
<Customer> Then, for this example, the resulting XML document is output directly to theResponse
object You see the resulting XML in the browser shown in Figure 10-10
Figure 10-10
Of course, it’s nice to see the resulting XML, but it’s far more useful to style that information with XSLT The XML Web Server control mentioned earlier is perfect for this task However, in Listing 10-22, rather than setting both theTransformSourceandDocumentSourceproperties as in Listing 10-25, you set only theTransformSourceproperty at design time, and theXmlDocumentis the one created in the code-behind
of Listing 10-21
547
Trang 2Listing 10-22: The ASPX Page and XSLT to style the XML from SQL Server
ASPX
<%@ Page Language="C#" CodeFile="Default.aspx.cs" Inherits="Default_aspx" %>
<asp:xml id="Xml1" runat="server" transformsource="~/customersToHtml.xslt"/>
XSLT
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"/>
<xsl:template match="/">
<h3>List of Customers</h3>
<table border="1">
<tr>
<th>Company Name</th><th>Contact Name</th><th>Contact Title</th>
</tr>
<xsl:apply-templates select="//Customer"/>
</table>
</xsl:template>
<xsl:template match="Customer">
<tr>
<td><xsl:value-of select="CompanyName"/></td>
<td><xsl:value-of select="ContactName"/></td>
<td><xsl:value-of select="ContactTitle"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
VB
’Response.ContentType = "text/xml"
’x.Save(Response.Output)
Xml1.XPathNavigator = xpathnav
C#
//Response.ContentType = "text/xml";
//x.Save(Response.Output);
Xml1.XPathNavigator = xpathnav;
In the code-behind file, the lines that setContentTypeand write the XML to theResponseobject are
commented out, and instead theXPathNavigatorfrom theXmlDocumentthat is manipulated in Listing
10-21 is set as a property of the XML Web Server control The control then performs the XSLTStylesheet
transformation, and the results are output to the browser, as shown in Figure 10-11
You have an infinite amount of flexibility within theSystem.Xml,System.Xml.Linq, andSystem.Data
namespaces Microsoft has put together a fantastic series of APIs that interoperate beautifully When
you’re creating your own APIs that expose or consume XML, compare them to the APIs that Microsoft
has provided — if you expose your data over anXmlReaderorIXPathNavigableinterface, you are sure
to make your users much happier Passing XML around with these more flexible APIs (rather than as
simple and opaque strings) provides a much more comfortable and intuitive expression of the XML
information set
Remember that the XmlReader that is returned from SqlCommand
.ExecuteXmlReader() is holding its SQL connection open, so you must call Close()
Trang 3when you’re done using the XmlReader The easiest way to ensure that this is done
is the using statement An XmlReader implements IDisposable and calls Close()
for you as the variable leaves the scope of the using statement.
Figure 10-11
SQL Server 2005 and the XML Data Type
You’ve seen that retrieving data from SQL Server 2000 is straightforward, if a little limited SQL
Server 2005, originally codenamed Yukon, includes a number of very powerful XML-based features
Dare Obasanjo, a former XML Program Manager at Microsoft has said, ‘‘The rise of the ROX
[Relational-Object-XML] database has begun.’’ SQL Server 2005 is definitely leading the way
One of the things that is particularly tricky about mapping XML and the XML information set to the
relational structure that SQL Server shares with most databases is that most XML data has a hierarchical structure Relational databases structure hierarchical data with foreign key relationships Relational data often has no order, but the order of the elements withinXmlDocumentis very important SQL Server 2005 introduces a new data type called, appropriately,XML Previously, data was stored in annvarcharor
other string-based data type SQL Server 2005 can now have a table with a column of typeXML, and each XML data type can have associated XML Schema
549
Trang 4TheFOR XMLsyntax is improved to include theTYPEdirective, so a query that includesFOR XML TYPE
returns the results as a single XML-typed value This XML data is returned with a new class called
System.Data.SqlXml It exposes its data as anXmlReaderretrieved by callingSqlXml.CreateReader, so
you’ll find it to be very easy to use because it works like all the other examples you’ve seen in
this chapter
In a DataSet returned from SQL Server 2005, XML data defaults to being a string
unless DataAdapter.ReturnProviderSpecificTypes = true is set or a schema is
loaded ahead of time to specify the column type.
TheXMLdata type stores data as a new internal binary format that is more efficient to query The
pro-grammer doesn’t have to worry about the details of how the XML is stored if it continues to be available
on the XQuery or inXmlReader You can mix column types in a way that was not possible in SQL Server
2000 You’re used to returning data as either a DataSet or anXmlReader With SQL Server 2005, you can
return a DataSet where some columns contain XML and some contain traditional SQL Server data types
Generating Custom XML from SQL 2005
You’ve seen a number of ways to programmatically generate custom XML from a database Before
read-ing this book, you’ve probably usedFOR XML AUTOto generate fairly basic XML and then modified the
XML in post processing to meet your needs This was formerly a very common pattern.FOR XML AUTO
was fantastically easy; andFOR XML EXPLICIT, a more explicit way to generate XML, was very nearly
impossible to use
SQL Server 2005 adds the newPATHmethod toFOR XML, which makes arbitrary XML creation
available to mere mortals SQL 2005’s XML support features very intuitive syntax and very clean
namespace handling
Here is an example of a query that returns custom XML TheWITH XMLNAMESPACEScommands at the start
of the query set the stage by defining a default namespace and using column-style name aliasing to
asso-ciate namespaces with namespace prefixes In this example,addr: is the prefix forurn:hanselman.com/
northwind/address
use Northwind;
WITH XMLNAMESPACES (
DEFAULT ’urn:hanselman.com/northwind’
, ’urn:hanselman.com/northwind/address’ as "addr"
)
SELECT CustomerID as "@ID",
CompanyName, Address as "addr:Address/addr:Street", City as "addr:Address/addr:City", Region as "addr:Address/addr:Region", PostalCode as "addr:Address/addr:Zip", Country as "addr:Address/addr:Country", ContactName as "Contact/Name",
ContactTitle as "Contact/Title", Phone as "Contact/Phone", Fax as "Contact/Fax"
FROM Customers
FOR XML PATH(’Customer’), ROOT(’Customers’), ELEMENTS XSINIL
Trang 5The aliases using theASkeyword declaratively describe the elements and their nesting relationships,
whereas thePATHkeyword defines an element for the Customers table TheROOTkeyword defines the
root node of the document
TheELEMENTSkeyword, along withXSINIL, describes how you handle null Without these keywords,
no XML element is created for a row’s column that contains null; this absence of data in the
database causes the omission of data in the resulting XML document When theELMENTS XSINIL
combination is present, an element outputs using an explicit xsi:nil syntax such as<addr:Region
xsi:nil="true" />
When you run the example, SQL 2005 outputs an XML document like the one that follows Note the
namespaces and prefixes are just as you defined them
<Customers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:addr="urn:hanselman.com/northwind/address"
xmlns="urn:hanselman.com/northwind">
<Customer ID="ALFKI">
<CompanyName>Alfreds Futterkiste</CompanyName>
<addr:Address>
<addr:Street>Obere Str 57</addr:Street>
<addr:City>Berlin</addr:City>
<addr:Region xsi:nil="true" />
<addr:Zip>12209</addr:Zip>
<addr:Country>Germany</addr:Country>
</addr:Address>
<Contact>
<Name>Maria Anders</Name>
<Title>Sales Representative</Title>
<Phone>030-0074321</Phone>
<Fax>030-0076545</Fax>
</Contact>
</Customer>
the rest of the document removed for brevity
The resulting XML can now be manipulated using anXmlReaderor any of the techniques discussed in
this chapter
Adding a Column of Untyped XML
SQL Server can produce XML from a query, and it can now also store XML in a single column Because XML is a first-class data type within SQL Server 2005, adding a new column to the Customers table of the Northwind Database is straightforward You can use any SQL Server management tool you like I use
the SQL Server Management Studio Express, a free download that can be used with any SQL SKU
(including the free SQL Express 2005) Bring up your Query Analyzer or Management Studio Express
and, with the Northwind database selected, execute the following query:
use Northwind;
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Customers ADD
Notes xml NULL
GO
COMMIT
551
Trang 6Note thexmltype keyword afterNotesin the preceding example If an XML Schema were already added
to the database, you could add this new column and associate it with a named Schema Collection all at
once using this syntax
use Northwind;
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Customers ADD
Notes xml(DOCUMENT dbo.NorthwindCollection)
GO
COMMIT
Here, the wordDOCUMENTindicates that the column will contain a complete XML document UseCONTENT
to store fragments of XML that don’t contain a root note You haven’t added a schema yet, so that’s the
next step So far, you’ve added aNotescolumn to the Customers table that can be populated with prose
For example, a customer service representative could use it to describe interactions she’s had with the
customer, entering text into a theoretical management system
Adding an XML Schema
Although the user could store untyped XML data in the Notes field, you should really include some
constraints on what’s allowed XML data can be stored typed or untyped, as a fragment with no root
note or as a document Because you want store Customer interaction data entered and viewed from a
Web site, ostensibly containing prose, XHTML is a good choice
XML data is validated by XML Schemas, as discussed earlier in the chapter However, SQL Server 2005
is a database, not a file system It needs to store the schemas you want to reference in a location it can get
to You add a schema or schemas to SQL Server 2005 using queries formed like this:
CREATE XML SCHEMA COLLECTION YourCollection AS ’your complete xml schema here’
You’ll be using the XHTML 1.0 Strict schema located on the W3C Web site shown here:
http://w3.org/TR/xhtml1-schema/#xhtml1-strict Copy the entire schema to a file, or download
the schema directly fromhttp://w3.org/2002/08/xhtml/xhtml1-strict.xsd
When executing your query, you include the entire XSD inline in your schema However, you should
watch for few things First, escape any single quotes so that’becomes’’— that is, two single quotes,
not one double — using a search and replace Second, because SQL 2005 uses the MSXML6 XML parser to
parse its XML, take into consideration a limitation in that parser MSXML6 already has thexml:
names-pace prefix and associated namesnames-pace hard-coded internally, so you should remove the line from your
schema that contains that namespace This little oddity is documented, but buried within MSDN at
http://msdn2.microsoft.com/ms177489(en-US,SQL.90).aspxand applies only to a few predefined
schemas like this one that uses thexml:prefix and/or thehttp://www.w3.org/XML/1998/namespace
namespace In the fragment that follows, I’ve bolded the line you need to remove
Use Northwind;
CREATE XML SCHEMA COLLECTION NorthwindCollection AS
’<?xml version="1.0" encoding="UTF-8"?>
<xs:schema version="1.0" xml:lang="en"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3.org/1999/xhtml"
Trang 7xmlns:xml="http://www.w3.org/XML/1998/namespace"
elementFormDefault="qualified">
the rest of the schema has been omitted for brevity
</xs:schema>’;
Instead, you want to execute a query like this, noting the single quote and semicolon at the very end
Use Northwind;
CREATE XML SCHEMA COLLECTION NorthwindCollection AS
’<?xml version="1.0" encoding="UTF-8"?>
<xs:schema version="1.0" xml:lang="en"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3.org/1999/xhtml"
xmlns="http://www.w3.org/1999/xhtml"
elementFormDefault="qualified">
the rest of the schema has been omitted for brevity
</xs:schema>’;
You may get a few schema validation warnings when you execute this query because of the complexity
of the XHTML schema, but you can ignore them Figure 10-12 shows the new NorthwindCollection
schemas added to the Northwind database
Figure 10-12
553
Trang 8Although Figure 10-12 shows the NorthwindCollection within the Object Explorer, you can also confirm
that your schema has been added correctly using SQL, as shown in the example that follows:
Use Northwind;
SELECT XSN.name
FROM sys.xml_schema_collections XSC
JOIN sys.xml_schema_namespaces XSN ON
(XSC.xml_collection_id = XSN.xml_collection_id)
The output of the query is something like the following You can see that the XHTML namespace appears
at the end along with the schemas that already existed in the system
http://www.w3.org/2001/XMLSchema
http://schemas.microsoft.com/sqlserver/2004/sqltypes
http://www.w3.org/XML/1998/namespace
http://www.w3.org/1999/xhtml
Next you should associate the new column with the new schema collection Using the Management
Studio, you create one composite script that automates this process In this case, however, you can
continue to take it step by step so you see what’s happening underneath
Associating a XML Typed Column with a Schema
You can use the Microsoft SQLServer Management Studio Express to associate the NorthwindCollection
with the new Notes column Open the Customers table of the Northwind Database and, within its
Col-umn collection, right-click and select Modify Select the Notes colCol-umn, as shown in Figure 10-13 Within
the Notes column’s property page, open the XML Type Specification property and select the
Northwind-Collection from the Schema Northwind-Collection dropdown Also, set theIs XML Documentproperty toYes
At this point, you can save your table and a change script is generated and executed If you want to see
and save the change script after making a modification but before saving the changes, right-click in the
grid and select Generate Change Script Click the Save toolbar button or Ctrl+S to commit your changes
to the Customers table
Now that you’ve added a new Notes column and associated it with an XHTML schema, you’re ready to
add some data to an existing row
Inserting XML Data into an XML Column
You start by adding some data to a row within the Northwind database’s Customer table Add
some notes to the famous first row, the customer named Alfreds Futterkiste, specifically CustomerID
ALFKI You add or update data to a column with the XML type just as you add to any data type For
example, you can try an UPDATE query
Use Northwind;
UPDATE Customers SET Notes = N’<HTML></HTML>’ WHERE CustomerID = ’ALFKI’;
Upon executing this query, you get this result:
Msg 6913, Level 16, State 1, Line 1
XML Validation: Declaration not found for element ’HTML’ Location: /*:HTML[1]
Trang 9What’s this? Oh, yes, you associated a schema with the XML column so the included document must
conform, in this case, to the XHTML specification Now, try again with a valid XHTML document that
includes a correct namespace
Use Northwind;
UPDATE Customers SET Notes = N’
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Notes about Alfreds</title>
</head>
<body>
<p>He is a nice enough fellow.</p>
</body>
</html>’
WHERE CustomerID = ’ALFKI’;
Figure 10-13
Execute this corrected query and you see a success message
(1 row(s) affected)
After you’ve typed a column as XML and associated an XML Schema, SQL Server 2005 will allow only
XML documents that validate The data can be retrieved from SQL Server using standard System.Data
555
Trang 10techniques It can be pulled out of aDataReaderor aDataSetand manipulated withXmlReaders or as an
XmlDocument
Summar y
XML and the XML InfoSet are both pervasive in the NET Framework and in ASP.NET All ASP.NET
configuration files include associated XML Schema, and the Visual Studio Editor is even smarter about
XML documents that use XSDs
XmlReaderandXmlWriterprovide unique and incredibly fast ways to consume and create XML; they
now also include even better support for mapping XML Schema types to CLR types, as well as other
improvements TheXmlDocumentandXPathDocumentreturn in NET 2.0 with API additions and
numer-ous performance improvements, while theXmlDataDocumentstraddles the world ofSystem.Dataand
System.Xml ASP.NET and NET 3.5 include support for XSLT via not only the new
XslCompiled-Transformbut also command-line compilation, and tops it all with XSLT debugging support for
com-piled stylesheets LINQ to XML introduces the newSystem.Xml.Linqnamespace and supporting classes
for a tightly integrated IntelliSense-supported coding experience VB9 takes XML support to the next
level with XML literals and XML namespace imports The bridge classes and extension methods make
the transition betweenSystem.XmlandSystem.Xml.Linqclean and intuitive
All these ways to manipulate XML via the Base Class Library are married with XML support in SQL
Server 2000 and 2005 SQL Server 2005 also includes the XML data type for storing XML in a first class
column type validated by XML Schemas stored in the database