Recipe15.9.Tearing Apart an XML Document


Recipe 15.9. Tearing Apart an XML Document

Problem

You have an XML document that needs to be broken apart into multiple parts. Each part can then be sent to a different destination (possibly a web service) to be processed individually. This solution is useful when you have a large document, such as an invoice, in XML form. For example, with an invoice, you would want to tear off the billing information and send this to Accounting, while sending the shipping information to Shipping, and then send the invoice items to Fulfillment to be processed.

Solution

In order to separate the invoice items, load an XmlDocument with the invoice XML from the Invoice.xml file shown in Example 15-6.

Example 15-6. Invoice.xml

 <?xml version="1.0" encoding="UTF-8"?> <Invoice invoiceDate='2003-10-05' invoiceNumber='INV-01'>     <shipInfo>         <name>Beerly Standing</name>         <attn>Receiving</attn>         <street>47 South Street</street>         <city>Intox</city>         <state>NH</state>     </shipInfo>     <billInfo>         <name>Beerly Standing</name>         <attn>Accounting</attn>         <street>98 North Street</street>         <city>Intox</city>         <state>NH</state>     </billInfo>     <Items>         <item partNum="98745">             <productName>Brown Eyed Stout</productName>             <quantity>12</quantity>             <price>23.99</price>             <shipDate>2003-12-20</shipDate>         </item>         <item partNum="34987">             <productName>Diamond Pearl Lager</productName>             <quantity>22</quantity>             <price>35.98</price>             <shipDate>2003-12-20</shipDate>         </item>         <item partNum="AK254">             <productName>Job Site Ale</productName>             <quantity>50</quantity>             <price>12.56</price>             <shipDate>2003-11-12</shipDate>         </item>      </Items>  </Invoice> 

The code to tear this invoice apart and send the various information pieces to their respective departments is shown in Example 15-7.

Example 15-7. Tearing apart an XML document (Invoice.xml)

 public static void ProcessInvoice() {      XmlDocument xmlDoc = new XmlDocument();      // Pick up invoice from deposited directory.      xmlDoc.Load(@"..\..\Invoice.xml");      // Get the Invoice element node.      XmlNode Invoice = xmlDoc.SelectSingleNode("/Invoice");     // Get the invoice date attribute.     XmlAttribute invDate =         (XmlAttribute)Invoice.Attributes.GetNamedItem("invoiceDate");      // Get the invoice number attribute.     XmlAttribute invNum =         (XmlAttribute)Invoice.Attributes.GetNamedItem("invoiceNumber");     // Process the billing information to Accounting.     WriteInformation(@"..\..\BillingEnvelope.xml",                     "BillingEnvelope",                     invDate, invNum, xmlDoc,                     "/Invoice/billInfo");     // Process the shipping information to Shipping.     WriteInformation(@"..\..\ShippingEnvelope.xml",                     "ShippingEnvelope",                     invDate, invNum, xmlDoc,                     "/Invoice/shipInfo");     // Process the item information to Fulfillment.     WriteInformation(@"..\..\FulfillmentEnvelope.xml",                     "FulfillmentEnvelope",                     invDate, invNum, xmlDoc,                     "/Invoice/Items/item");     // Now send the data to the web services … } private static void WriteInformation(string path,                              string rootNode,                              XmlAttribute invDate,                              XmlAttribute invNum,                              XmlDocument xmlDoc,                              string nodePath) {      XmlWriterSettings settings = new XmlWriterSettings();      settings.Indent = true;      using (XmlWriter writer =         XmlWriter.Create(path, settings))     {          writer.WriteStartDocument();          writer.WriteStartElement(rootNode);          writer.WriteAttributeString(invDate.Name, invDate.Value);          writer.WriteAttributeString(invNum.Name, invNum.Value);         XmlNodeList nodeList = xmlDoc.SelectNodes(nodePath);         // Add the billing information to the envelope.         foreach (XmlNode node in nodeList)         {             writer.WriteRaw(node.OuterXml);         }         writer.WriteEndElement();         writer.WriteEndDocument();     }  } 

The "envelopes" containing the various pieces of XML data for the web services are listed below.


BillingEnvelope XML

 <BillingEnvelope invoiceDate="2003-10-05" invoiceNumber="INV-01">     <billInfo>         <name>Beerly Standing</name>         <attn>Accounting</attn>         <street>98 North Street</street>         <city>Intox</city>         <state>NH</state>     </billInfo> </BillingEnvelope> 


ShippingEnvelope XML

 <ShippingEnvelope invoiceDate="2003-10-05" invoiceNumber="INV-01">     <shipInfo>         <name>Beerly Standing</name>         <attn>Receiving</attn>         <street>47 South Street</street>         <city>Intox</city>         <state>NH</statey>     </shipInfo> </ShippingEnvelope> 


FulfillmentEnvelope XML

 <FulfillmentEnvelope invoiceDate="2003-10-05" invoiceNumber="INV-01">     <item partNum="98745">         <productName>Brown Eyed Stout</productName>         <quantity>12</quantity>         <price>23.99</price>         <shipDate>2003-12-20</shipDate>     </item>     <item partNum="34987">         <productName>Diamond Pearl Lager</productName>         <quantity>22</quantity>         <price>35.98</price>         <shipDate>2003-12-20</shipDate>     </item>     <item partNum="AK254">         <productName>Job Site Ale</productName>         <quantity>50</quantity>         <price>12.56</price>         <shipDate>2003-11-12</shipDate>     </item> </FulfillmentEnvelope> 

Discussion

In order to tear apart the invoice, you need to establish what pieces go to which departments. The breakdown of this is that each of the envelopes gets the invoice date and invoice number from the main invoice to give context to the information in the envelope. The billInfo element and children go to the BillingEnvelope, the shipInfo element and children go to the ShippingEnvelope, and the item elements go to the FulfillmentEnvelope. Once these envelopes are constructed, they are sent to the web services for each department to perform its function for this invoice.

In the example program from the Solution, you first load the Invoice.xml file and get the attributes you are going to give to each of the envelopes:

 XmlDocument xmlDoc = new XmlDocument( ); // Pick up invoice from deposited directory. xmlDoc.Load(@"..\..\Invoice.xml"); // Get the Invoice element node. XmlNode Invoice = xmlDoc.SelectSingleNode("/Invoice"); // Get the invoice date attribute. XmlAttribute invDate =     (XmlAttribute)Invoice.Attributes.GetNamedItem("invoiceDate"); // Get the invoice number attribute. XmlAttribute invNum =     (XmlAttribute)Invoice.Attributes.GetNamedItem("invoiceNumber"); 

Then you establish each envelope with the sections of the invoice that matter to the respective functions (the BillingEnvelope is handled by Accounting, the ShippingEnvelope is handled by Shipping, and the FulfillmentEnvelope is handled by Fulfillment) by calling the WriteInformation method, starting with the BillingEnvelope:

     // Process the billing information to Accounting.     WriteInformation(@"..\..\BillingEnvelope.xml",                     "BillingEnvelope",                     invDate, invNum, xmlDoc,                     "/Invoice/billInfo"); 

Then the ShippingEnvelope is created:

 // Process the shipping information to Shipping. WriteInformation(@"..\..\ShippingEnvelope.xml",                     "ShippingEnvelope",                     invDate, invNum, xmlDoc,                     "/Invoice/shipInfo"); 

Finally, the FulfillmentEnvelope is created:

 // Process the item information to Fulfillment. WriteInformation(@"..\..\FulfillmentEnvelope.xml",                     "FulfillmentEnvelope",                      invDate, invNum, xmlDoc,                      "/Invoice/Items/item"); 

At this point, each of the envelopes can be posted to the respective web services interfaces.

When you append the attributes from the Invoice to the envelopes, you call the XmlNode.Clone method on the XmlAttributes. This is done so that each of the elements has its own separate copy. If you do not do this, then the attribute will appear only on the last element it is assigned to.


See Also

See the "XmlDocument Class," "XmlElement Class," and "XmlAttribute Class" topics in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

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