Reputation: 2724
I'm trying to reformat my XML code so it's easier to read. At the moment it looks like this:
<Settings>
<Display_Settings>
<ScreenName Name="1">1</ScreenName>
<ScreenTag Tag="1">1</ScreenTag>
<LocalPosition X="1" Y="1" Z="1">0.000, 0.000, 0.000</LocalPosition>
<Width Width="0.000">0.000</Width>
<Height Height="0.000">0.000</Height>
</Display_Settings>
</Settings>
However what I want it look like is this:
<Settings>
<Display_Settings>
<ScreenName Name="1">1
<ScreenTag Tag="1">1</ScreenTag>
<LocalPosition X="1" Y="1" Z="1">0.000, 0.000, 0.000</LocalPosition>
<Width Width="0.000">0.000</Width>
<Height Height="0.000">0.000</Height>
</ScreenName>
</Display_Settings>
</Settings>
Ok, rubbish example but I hope you get the jist; I want all of my values like tag and local position etc to be a child of the screen name. Now I know that to do this it would normally be the following call:
XmlNode _rootNode; // in the above i'll have set this to be Display_Settings
_rootNode.AppendChild(_screenTag);
But, I've set my XML creation code in a list that is held in one class and populated in another. It looks like this:
Generate XML
public HV_WriteXML()
{
//root node
_rootNode = _xmlDoc.CreateElement("InMo_Settings");
_xmlDoc.AppendChild(_rootNode);
_userNode = _xmlDoc.CreateElement("Display_Settings");
_rootNode.AppendChild(_userNode);
}
public void GenereateSettingsFile(List<Node> nodeList, string filePath)
{
_rootNode.RemoveChild(_userNode);
_userNode = _xmlDoc.CreateElement("Display_Settings");
_rootNode.AppendChild(_userNode);
foreach (Node n in nodeList)
{
foreach (XmlElement e in n.GenerateXML(_xmlDoc))
{
_userNode.AppendChild(e);
}
}
_xmlDoc.Save(filePath);
}
Then to fill this out, I'm doing the following in a derived class:
public override List<XmlElement> GenerateXML(XmlDocument _xmlDoc)
{
List<XmlElement> elementList = new List<XmlElement>();
if (nodeDictionary.ContainsKey("Name "))
{
XmlElement _screenName = _xmlDoc.CreateElement("ScreenName");
_screenName.SetAttribute("Name", (string)nodeDictionary["Name "].value);
_screenName.InnerText = (string)nodeDictionary["Name "].value;
elementList.Add(_screenName);
}
if (nodeDictionary.ContainsKey("Tag"))
{
XmlElement _screenTag = _xmlDoc.CreateElement("ScreenTag");
_screenTag.SetAttribute("Tag", (string)nodeDictionary["Tag"].value);
_screenTag.InnerText = (string)nodeDictionary["Tag"].value;
elementList.Add(_screenTag);
}
}
Now my real question is how do I append my _screenTag element so that its a child of my screen name when I've set up the creation of my xml in a list in a different class?
Upvotes: 1
Views: 3479
Reputation: 4352
You can insert the desired tag anywhere in the XML by follows,
//Get Display_Settings node
XmlNode displaySettingsNode = xmlDoc.SelectSingleNode(@"Settings/Display_Settings");
//Get LocalPosition node
XmlNode screenNameNode = xmlDoc.SelectSingleNode(@"Settings/Display_Settings/LocalPosition");
//Create Screen Tag
XmlElement screenTag = xmlDoc.CreateElement("ScreenTag");
screenTag.SetAttribute("Tag", (string)nodeDictionary["Tag"].value);
screenTag.InnerText = (string)nodeDictionary["Tag"].value;
//Insert Screen Tag node in desired location
displaySettingsNode.InsertBefore(screenTag, screenNameNode);
Upvotes: 1
Reputation: 35353
How about this? (using LinqToXml)
var xDoc = XDocument.Parse(xmlstring); //or XDocument.Load(filename)
var elems = xDoc.Descendants("Display_Settings")
.First()
.Elements()
.Where(e => e.Name.LocalName != "ScreenName")
.ToList();
elems.ForEach(e => e.Remove());
xDoc.Descendants("ScreenName").First().Add(elems);
var newxml = xDoc.ToString();
Upvotes: 0
Reputation: 1704
It seems to me that the difficulty that you have is a schema mismatch between your c# data structure and the desired XML data structure.
i.e. Your list is a 'flat' structure, but the desired XML has nesting.
Ideally you should refactor your code so that the two are more similar, you could create a c# model object for Display_Settings and then add child properties to that class as appropriate. This might allow you to use .Net built in XML serialisation instead of having to hand-crank it as you are now.
Alternatively, if you are stuck with the manual XML creation, you could use the inherent support for tree structures that is in the XmlElement class, i.e. use the ChildNodes property: http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.childnodes.aspx
Upvotes: 1