Solved

Adding an Attribute to an XML Element

Posted on 2004-10-04
9
501 Views
Last Modified: 2013-11-19
I have an XML document, and I would like to add an attribute to a particular element. For example, in the following XML (not fully shown), there is an element called s:any:

...
<s:element name="TypedDataSet">
  <s:complexType>
    <s:sequence>
      <s:any />
    </s:sequence>
  </s:complexType>
</s:element>
...

I want to add an attribute namespace="http://www.tempuri.org/TypedDataSet.xsd" to all elements with s:any name. In the above example, the result will be like:

...
<s:element name="TypedDataSet">
  <s:complexType>
    <s:sequence>
      <s:any namespace="http://www.tempuri.org/TypedDataSet.xsd"/>
    </s:sequence>
  </s:complexType>
</s:element>
...

I would appreciate a full example showing how to read the XML document, adding in the attribute, and saving the document.

Thanks in advance.
0
Comment
Question by:yongsing
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
9 Comments
 
LVL 3

Expert Comment

by:KeithWatson
ID: 12219853
OK, this should do the trick; it shows reading from a string literal and from disk.

You need to include:

using System.Xml;
using System.IO;

// I had to remove the namespace prefix; you've only supplied part of the XML document (it won't parse without it)
string s = "<element name='TypedDataSet'><complexType><sequence><any /></sequence></complexType></element>";

XmlDocument document = new XmlDocument();
document.LoadXml(s);

// Alternative, to read from a file on disk rather from the string above
// document.Load(new XmlTextReader("file://c:\\test.xml"));

// This may have to change to "//s:any" in your document
XmlElement element = (XmlElement) document.SelectSingleNode("//any");

element.SetAttribute("namespace", "http://www.tempuri.org/TypedDataSet.xsd");

// Write the output to a file on disk

StreamWriter writer = new StreamWriter("c:\\testoutput.xml");
writer.Write(document.InnerXml);
writer.Close();


Hope that helps.
0
 
LVL 3

Expert Comment

by:KeithWatson
ID: 12219896
Incidentally, I was perhaps a little terse on the XPath statement; you may be better with a precise path such as:

XmlElement element = (XmlElement) document.SelectSingleNode("/element/complexType/sequence/any");

(Which as I stated you may need to qualify with the "s" namespace prefix")

Keith.
0
 
LVL 9

Author Comment

by:yongsing
ID: 12227195
Thanks, it works.

If the "any" element is qualified with some other unknown namespace, can I still add the attribute? For example, it could be qualified with "xxx" or even not qualified with any namespace. In other words, I want to add the attribute to all elements with the name "any" regardless of what namespace it is qualified with.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Expert Comment

by:KeithWatson
ID: 12243728
If you can get a reference to the node without knowing the namespace (which is perfectly possible) then yes. The implementation of XPath I've used most does insist that you qualify XPath expressions with namespaces, which makes sense, since they are effectively differently named nodes, in the same way that two classes in C# with the same name but living in different namespaces are distinct entities in their own right.

You could write a similar program however not using XPath that recursed down all of the nodes in the tree looking for nodes with the name "Any" and performing exactly the same operation as above on each of these elements.
0
 
LVL 9

Author Comment

by:yongsing
ID: 12274902
Hi, sorry for not getting back earlier. For your suggestion of recursing  down all of the nodes in the tree looking for nodes with the name "any", can you provide an example? Thanks!
0
 
LVL 3

Accepted Solution

by:
KeithWatson earned 300 total points
ID: 12281414
Here's some sample code... Note that the second method calls itself (i.e. it's recursive).


private void testMethod() {

      /* Make a test string */
      string testXmlString = "<Test><Node2><Keith></Keith></Node2></Test>";

      /* Load this into an XmlDocument object */
      XmlDocument document = new XmlDocument();
      document.LoadXml(testXmlString);

      /* Get a handle to the root node of the document */
      XmlElement rootNode = (XmlElement) document.ChildNodes.Item(0);

      /* Call the recursive function looking to add the namespace attribute to nodes named 'Keith' */
      addAttributeToNodeWithName(rootNode, "Keith");

      /* Write the document as it is now to the console */
      Console.WriteLine(document.OuterXml);

}



private void addAttributeToNodeWithName(XmlElement node, string withName) {

      /* If this node matches the pattern, add the namespace attribute */

      if (node.Name.Equals(withName)) {
            node.SetAttribute("namespace", "Keith");
      }

      /* Recurse on any children and do the same thing with them */
            
      foreach (XmlElement childNode in node.ChildNodes) {
            addAttributeToNodeWithName(childNode, withName);
      }

}


0
 
LVL 9

Author Comment

by:yongsing
ID: 12298487
Hi Keith, thanks.

If I add the following to the XML, it won't work:

string testXmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                 "<Test><Node2><Keith></Keith></Node2></Test>";

There will be an exception on this line:
XmlElement rootNode = (XmlElement) document.ChildNodes.Item(0);

It can be fixed by changing the index from 0 to 1:
XmlElement rootNode = (XmlElement) document.ChildNodes.Item(1);

How can I know that there is a <?xml ... ?> in front?
0
 
LVL 9

Author Comment

by:yongsing
ID: 12298734
I just found out that you need to check whether the type is XmlElement:

for (int i = 0; i < document.ChildNodes.Count; i++)
{
   if (document.ChildNodes.Item(i) is XmlElement)
   {
      XmlElement xmlElement = (XmlElement)document.ChildNodes.Item(i);
      addAttributeToNodeWithName(xmlElement, "any");
   }
}

I'll get back to you again... :)
0
 
LVL 9

Author Comment

by:yongsing
ID: 12299237
Thanks Keith, I finally got what I want!
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

738 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question