1

I have an XML string that is loaded into an XMLDocument, similar to the one listed below:

  <note>
   <to>You</to> 
   <from>Me</from> 
   <heading>TEST</heading> 
   <body>This is a test.</body> 
  </note>

I would like to convert the text nodes to attributes (using C#), so it looks like this:

<note to="You" from="Me" heading="TEST" body="This is a test." />

Any info would be greatly appreciated.

1

3 Answers 3

2

Linq to XML is great for this kind of stuff. You could probably achieve it in one line if you'd want to. Just grab the child node names and their respective value and add all those 'key value pairs' as attributes instead.

MSDN docs here: http://msdn.microsoft.com/en-us/library/bb387098.aspx

Sign up to request clarification or add additional context in comments.

2 Comments

Found this on MSDN: XElement root = XElement.Load("Data.xml"); foreach (XAttribute att in root.Attributes()) { root.Add(new XElement(att.Name, (string)att)); } root.Attributes().Remove(); Console.WriteLine(root); It converts attributes to elements. Not sure how to change it to do what I need (change elements to attributes).
Had some time to play with the above code and got it to do what I need. Here it is: foreach (XElement el in root.Elements()) { root.Add(new XAttribute(el.Name, (string)el)); } root.Elements().Remove(); Console.WriteLine(root); @seldon, thank you for pointing me in the right direction.
0

Like seldon suggests, LINQ to XML would be a much better fit for this sort of task.

But here's a way to do it with XmlDocument. Not claiming this is fool-proof (haven't tested it), but it does seem to work for your sample.

XmlDocument input = ...

// Create output document.
XmlDocument output = new XmlDocument();

// Create output root element: <note>...</note>
var root = output.CreateElement(input.DocumentElement.Name);

// Append attributes to the output root element
// from elements of the input document.
foreach (var child in input.DocumentElement.ChildNodes.OfType<XmlElement>())
{
    var attribute = output.CreateAttribute(child.Name); // to
    attribute.Value = child.InnerXml; // to = "You"
    root.Attributes.Append(attribute); // <note to = "You">
}

// Make <note> the root element of the output document.
output.AppendChild(root);

2 Comments

Seldon and Ani. Thank you for both of the suggestions. I'm not experienced using Link to XML, so I am not sure how to implement it that way. Using Ani's method, I get an error (System.Xml.NodeList does not contain a definition for 'OfType')
Thank you. Adding the first directive (system.linq) worked. Would you happen to know how to do it using Linq to XML? I put some code that I found on MSDN that does the opposite of what I need. Trying to modify it to change elements to attributes. It's posted below Seldon's original response. Thank you again. Your help is very much appreciated.
0

Following converts any simple XML leaf node into an attribute of its parent. It is implemented as a unit test. Encapsulate your XML content into an input.xml file, and check it saved as output.xml.

using System;
using System.Xml;
using System.Linq;
using NUnit.Framework;

[TestFixture]
public class XmlConvert
{
    [TestCase("input.xml", "output.xml")]
    public void LeafsToAttributes(string inputxml, string outputxml)
    {
        var doc = new XmlDocument();
        doc.Load(inputxml);
        ParseLeafs(doc.DocumentElement);
        doc.Save(outputxml);
    }

    private void ParseLeafs(XmlNode parent)
    {
        var children = parent.ChildNodes.Cast<XmlNode>().ToArray();
        foreach (XmlNode child in children)
            if (child.NodeType == XmlNodeType.Element
                && child.Attributes.Count == 0
                && child.ChildNodes.Count == 1
                && child.ChildNodes[0].NodeType == XmlNodeType.Text
                && parent.Attributes[child.Name] == null)
            {
                AddAttribute(parent, child.Name, child.InnerXml);
                parent.RemoveChild(child);
            }
            else ParseLeafs(child);

        // show no closing tag, if not necessary
        if (parent.NodeType == XmlNodeType.Element
            && parent.ChildNodes.Count == 0)
            (parent as XmlElement).IsEmpty = true;
    }

    private XmlAttribute AddAttribute(XmlNode node, string name, string value)
    {
        var attr = node.OwnerDocument.CreateAttribute(name);
        attr.Value = value;
        node.Attributes.Append(attr);
        return attr;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.