Archive for category XML

C#: Adding CData Sections to an Existing Node using XmlDocument and XDocument to handle HTML code or other problematic characters

There are situations where the data within nodes of Xml need to be handled due to special characters or html type tags. To handle that one must place data into CData sections. This artcle shows one how to do that in .Net using C# for both the XMLDocument as well as the XDocument.

XMLDocument Example

string myXml =
@"<?xml version='1.0' encoding='utf-8'?>
<WorkingSet>
 <Data>
 </Data>
</WorkingSet>";

XmlDocument doc1 = new XmlDocument();
doc1.LoadXml( myXml );

XmlNode target = doc1.SelectSingleNode( "WorkingSet/Data" );

if (target != null)
    target.AppendChild( doc1.CreateCDataSection( "<h1>Hello</h1>" ) );

XDocument Example

XDocument doc = XDocument.Parse( myXml, LoadOptions.SetLineInfo );

XElement dataNode = doc.Descendants( "Data" ).First();

dataNode.Add ( new XCData( "<h1>Hello</h1>" ));

Console.WriteLine( doc.ToString() );

Results

<?xml version="1.0" encoding="utf-8"?>
<WorkingSet>
 <Data><![CDATA[<h1>Hello</h1>]]></Data>
</WorkingSet>
  • Share/Bookmark

Tags: , ,

Tribal Knowledge: C# XDocument Copy Xml But Remove the Pesky DocType

stockxpertcom_id7474751_jpg_882845b5f523a87946c1e89ba7bb9621 In another of my series of Tribal Knowledge articles, this one discusses the basics of loading an XDocument and creating a different document from that original.

There may be a need for one to remove the document type from the original XDocument in C#, or do a basic copy and this is presented here.

How-To

Here is the Xml in a classic before:

<?xml version='1.0' encoding='utf-8'?>
<!-- Generator: AVG Magician 1.0.0, AVG Exports Plug-In . AVG Version: 2.00 Build 8675309)  -->
<!DOCTYPE svg PUBLIC '-//W3C//DTD AVG 1.1//EN' 'http://www.w3.org/Graphics/AVG/1.1/DTD/avg11.dtd'[]>
<avg version='1.1' id='Layer_1' x='0px' y='0px' xml:space='preserve'>
    <rect x='100.143' y='103.714' fill='none' width='87.857' height='12.143' />
</avg>

and this is what we want to achieve:

<?xml version='1.0' encoding='utf-8'?>
<avg version="1.1" id="Layer_1" x="0px" y="0px" xml:space="preserve">
    <rect x="100.143" y="103.714" fill="none" width="87.857" height="12.143" />
</avg>

Since we only care about the AVG node, its the main root, we will simply get that node and append it to our new clone. Here is the full code:

string xml = @"<?xml version='1.0' encoding='utf-8'?>
<!-- Generator: AVG Magician 1.0.0, AVG Export Plug-In . AVG Version: 2.00 Build 8675309)  -->
<!DOCTYPE svg PUBLIC '-//W3C//DTD AVG 1.1//EN' 'http://www.w3.org/Graphics/AVG/1.1/DTD/avg11.dtd'[]>
<avg version='1.1' id='Layer_1' x='0px' y='0px' xml:space='preserve'>
    <rect x='100.143' y='103.714' fill='none' width='87.857' height='12.143' />
</avg>";

XDocument loaded = XDocument.Parse( xml, LoadOptions.SetLineInfo );

XDocument clone = new XDocument( new XDeclaration( "1.0", "utf-8", "yes"),
    loaded.LastNode
    );

Console.WriteLine( clone );

The above achieves the after Xml which we seek, no DocType, we didn’t add it and no first node which is the comment line. I hope this little example helps.

  • Share/Bookmark

Tags: ,

C# XML Parsing Extracting Values and using XML to Linq with XDocument

On my blog the most accessed articles are the basic ones on XML which has suprised me. So In this article I will focus on the new kid on the block the Linq derived XDocument. In the following example I will load the Xml then enumerate over the child nodes, to extract specific values and then display them.

I am loading the xml directly, but you can load it from other locations using the Load option of XDocument.

string xml = @"<?xml version='1.0' encoding='UTF-8'?>
<widgets>
    <widget>
        <url>~/Portal/Widgets/ServicesList.ascx</url>
        <castAs>ServicesWidget</castAs>
        <urlType>ascx</urlType>
        <parameters>
            <PortalCategoryId>3</PortalCategoryId>
        </parameters>
    </widget>
    <widget>
        <url>www.omegacoder.com</url>
        <castAs>ServicesWidget</castAs>
        <urlType>htm</urlType>
        <parameters>
            <PortalCategoryId>41</PortalCategoryId>
        </parameters>
    </widget>
</widgets>";

XDocument loaded = XDocument.Parse( xml );

var widgets = from x in loaded.Descendants( "widget" )
              select new
              {
                  URL = x.Descendants( "url" ).First().Value,
                  Category = x.Descendants( "PortalCategoryId" ).First().Value
              };

foreach ( var wd in widgets )
    Console.WriteLine( "Widget at ({0}) has a category of {1}", wd.URL, wd.Category );

/* Outputs:

Widget at (~/Portal/Widgets/ServicesList.ascx) has a category of 3
Widget at (www.omegacoder.com) has a category of 41

*/
  • Share/Bookmark

Tags: , ,

XPath meets Linq To XML in C#

There are two technologies which I feel that every coder should learn regardless of the language one programs in…those are Regular Expressions and XPath.

XPath is a quirkier language than Regular Expressions, but it is the the linqua-franca for working with xml documents. By specifying an XPath query which mirrors the target nodes one can get nodes from an xml document to be processed in the code.

The forum poster had xml data with a missing node, he had a car example. He wanted all the parent car nodes which had three tires (child nodes) and did not have four. Three wheel cars verse four wheel cars.

The following C# shows how to manipulate the Xpath and retrieve the nodes needed. Note one uses an xml editor with Xpath editing to figure out the stranger derivations.

using System.Xml.Linq;
using System.Xml.XPath;

...

string xml= @"<?xml version='1.0' encoding='UTF-8'?>
<Main>
<cars>
    <car name='Twingo'>
        <wheel1>abc</wheel1>
        <wheel2>def</wheel2>
        <wheel3>ghi</wheel3>
    </car>
    <car name='quattro'>
        <wheel1>some info</wheel1>
        <wheel2>more info</wheel2>
        <wheel3>blur</wheel3>
        <wheel4>We have four tires</wheel4>
    </car>
    <car name='Triumph'>
        <wheel1>some info</wheel1>
        <wheel2>more info</wheel2>
        <wheel3>blur</wheel3>
    </car>
</cars>
</Main>";

XDocument loaded = XDocument.Parse( xml );

IEnumerable<XElement> list1
   = loaded.XPathSelectElements( "//cars/car[not(wheel4)]" );

foreach ( XElement el in list1 )
    Console.WriteLine( el );

/* Outputs
<car name="Twingo">
  <wheel1>abc</wheel1>
  <wheel2>def</wheel2>
  <wheel3>ghi</wheel3>
</car>
<car name="Triumph">
  <wheel1>some info</wheel1>
  <wheel2>more info</wheel2>
  <wheel3>blur</wheel3>
</car>*/
  • Share/Bookmark

Tags: , , ,

Replace Xml Node with Raw Xml in .Net

In this post I will simulate a user editing a raw XmlNode from an existing xml document. Say for example we extract the node to edit, with subnodes, and place that in a text box. The user edits the text adding whatever is needed, but keeping with the original nodes, and then signals they are done. Upon that signal we take that raw fragment from the textbox and insert it into the document. Here is the code:

   1: string xmlInitial =
   2: @"<?xml version='1.0'?>
   3: <Rules>
   4:     <OpenBalances function='ReOrderFifo'>
   5:         <column name='SecurityID' used='True'/>
   6:         <column name='COL2' used='False'>#@#</column>
   7:         <column name='COL3' used='False'>#@#</column>
   8:     </OpenBalances>
   9:     <ClosedBalances/>
  10: </Rules>";
  11:
  12: string xmlCreatedByTheUser =
  13: @"<OpenBalances function='ReOrderFifo' iAmNew='true'>
  14:     <column name='SecurityID' used='True'/>
  15:     <column name='COL2' used='False'>#@#</column>
  16:     <column name='COL3' used='False'>#@#</column>
  17: </OpenBalances>";
  18:
  19:     XmlDocument originalXml = new XmlDocument();
  20:
  21:     string targetNode = "descendant::*[name(.) ='OpenBalances']";
  22:
  23:     originalXml.LoadXml(xmlInitial);
  24:
  25:     // Simulate the selection of the subnode
  26:     // for the user to edit in the first nodes
  27:     // Rules.
  28:     XmlNode editNode = originalXml.SelectSingleNode(targetNode);
  29:
  30:     // Get a fragment and slide the changed data into it.
  31:     XmlDocumentFragment fragment = originalXml.CreateDocumentFragment();
  32:     fragment.InnerXml = xmlCreatedByTheUser;
  33:
  34:     // Replace the contents of the editNode with the user fragment.
  35:     editNode.ParentNode.ReplaceChild(fragment, editNode);
  36:
  37:     Console.WriteLine(originalXml.OuterXml);
  • Line 01: This is our original Xml which we will use.
  • Line 12: This is the simulated change by the user. The user adds one attribute iAmNew.
  • Line 21: We will use this Xpath to extract the node to work on for the user.
  • Line 23: We load the initial Xml into the document.
  • Line 28: Simulated extraction of the node to display to the user.
  • Line 31: Its important that we create a Xml fragment from our original XmlDocument. We could not prune another XmlDocument, or create a fragment on the fly, it must come from the original Xml.
  • Line 32: Simulated user change and loading from a TextBox.
  • Line 35: Do the replacement here.
  • Line 37: Output the Xml.

Console Output:

   1: <?xml version="1.0"?>
   2: <Rules>
   3:    <OpenBalances function="ReOrderFifo" iAmNew="true">
   4:        <column name="SecurityID" used="True" />
   5:        <column name="COL2" used="False">##@##</column>
   6:        <column name="COL3" used="False">##@##</column>
   7:    </OpenBalances>
   8:    <ClosedBalances />
   9: </Rules>
  • Share/Bookmark

Tags:

Add Attribute to XmlDocument in .Net

Here is an example of adding an attribute to an XmlDocument in C# and .Net. The below code reads in Xml. Where there are nodes that do not contain and ID attribute, we will add that attribute using the name as the value.

   1: public static string xmlAcct =
   2: @"<?xml version='1.0' encoding='utf-8'?>
   3: <Accounts>
   4: <acct acct='aex113' country_code='us' name='abcde' />
   5: <acct acct='aex114' name='eeaad' country_code='us' />
   6: <acct acct='aex115' country_code='us' name='eoo' id='eoo9' />
   7: </Accounts>
   8: ";
   9:
  10: public static void AddAttribute()
  11: {
  12:
  13:     XmlDocument originalXml = new XmlDocument();
  14:
  15:
  16:     originalXml.LoadXml(xmlAcct);
  17:
  18:     XmlNodeList accts
  19:        = originalXml.SelectNodes("descendant::*[name(.) ='acct']");
  20:     XmlNode temp;
  21:     XmlNode name;
  22:     XmlAttribute attr;
  23:
  24:     foreach (XmlNode current in accts)
  25:     {
  26:         temp = current.SelectSingleNode("@id");
  27:         if (temp == null)
  28:         {
  29:             name = current.SelectSingleNode("@name");
  30:             if (name != null)
  31:             {
  32:                 attr = originalXml.CreateAttribute("id");
  33:                 attr.InnerText = name.InnerText;
  34:                 current.Attributes.Append(attr);
  35:             }
  36:         }
  37:
  38:     }
  39:
  40:     Console.WriteLine(originalXml.OuterXml);
  41:
  42:
  43: }
  • Line 01: Create Test XMl
  • Line 16: Load the test Xml.
  • Line 19: Get all the account nodes using Xpath.
  • Line 24: Work through each account node to add an attribute if ID does not exist.
  • Line 27: When null we need to add the ID node.
  • Line 29: We will use the name as the ID.
  • Line 32: We have to create the attribute off of the current node. Very important, for we can’t just slap any old node on. It has to be from the current branch/node.
  • Line 40: Display the changes.
  • Share/Bookmark

Tags: ,

Xml handling using XmlDocument and Xpath

This is a quick example of loading data into and XmlDocument and then extracting data using XPath. Each of those topics have books written on them and one can surely use this sample as a starting point for that learning.

Note the Xpath used does not demonstate the full capabilities of Xpath such as one can extract attributes off of nodes using the @ sign.

   1: XmlDocument xd = new XmlDocument();
   2:
   3: xd.LoadXml(
   4: @"<?xml version='1.0'?>
   5:     <Wrapper>
   6:         <myData>some stuff</myData>
   7:         <level access='t'>4</level>
   8:         <size>medium</size>
   9:    </Wrapper>");
  10:
  11: XmlNode node
  12:     = xd.SelectSingleNode(
  13:         "descendant::*[name(.) ='myData']");
  14:
  15: Console.WriteLine("Inner Text ({0}) Outer Xml {1}",
  16:                   node.InnerText,
  17:                   node.OuterXml);
  18:
  • Line 1 Create a new XmlDocument.
  • Line 3 Load the Xml from a string, other ways one could load from a file.
  • Line 11-13 We are interested in getting the first node encountered thats name is myData. By using the SelectSingleNode we can get just one.
  • Line 13 This is a generic Xpath that I like to use which can get information from the current node looked being looked at. What it is saying is,Looking at all the decendants of the current node, give me the node where the name found is myData.
  • Line 15 We are not checking to see if node is null. In normal code this is a no-no, check before usage!
  • Line 16 The actual data is store in the InnerText of the node, which we will extract.
  • Line 17 Sometimes we need the xml along with it, see below.

This is what the output looks like:

Inner Text (some stuff) Outer Xml <myData>some stuff</myData>

  • Share/Bookmark

Tags: ,

OmegaMan's Musings is Digg proof thanks to caching by WP Super Cache