I want to select one < NodeLabel > Tag. Selection should be done, when the < NodeLabel > has Elements.
The xml File looks like
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.14.2-->
<key attr.name="description" attr.type="string" for="graph" id="d0" />
<key for="port" id="d1" yfiles.type="portgraphics" />
<key for="port" id="d2" yfiles.type="portgeometry" />
<key for="port" id="d3" yfiles.type="portuserdata" />
<key attr.name="url" attr.type="string" for="node" id="d4" />
<key attr.name="description" attr.type="string" for="node" id="d5" />
<key for="node" id="d6" yfiles.type="nodegraphics" />
<key for="graphml" id="d7" yfiles.type="resources" />
<key for="edge" id="d8" yfiles.type="portconstraints" />
<key attr.name="url" attr.type="string" for="edge" id="d9" />
<key attr.name="description" attr.type="string" for="edge" id="d10" />
<key for="edge" id="d11" yfiles.type="edgegraphics" />
<graph edgedefault="directed" id="G">
<data key="d0" />
<node id="n0" yfiles.foldertype="group">
<data key="d6">
<y:TableNode configuration="YED_TABLE_NODE">
<y:Geometry height="646.8359897640048" width="1012.9110704527719" x="0.0" y="-646.8359897640048" />
<y:Fill color="#ECF5FF" color2="#0042F440" transparent="false" />
<y:BorderStyle color="#000000" type="line" width="1.0" />
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="22.37646484375" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="230.7578125" x="391.07662897638596" y="4.0">title</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="54.712890625" x="111.14444510514247" y="33.0">col0<y:LabelModel><y:ColumnNodeLabelModel offset="3.0" /></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_0" inside="true" verticalPosition="0.0" /></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="72.712890625" x="482.3174666703262" y="33.0">col1<y:LabelModel><y:ColumnNodeLabelModel offset="3.0" /></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_1" inside="true" verticalPosition="0.0" /></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="58.046875" x="869.6051192915697" y="33.0">col2<y:LabelModel><y:ColumnNodeLabelModel offset="3.0" /></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_2" inside="true" verticalPosition="0.0" /></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" rotationAngle="270.0" textColor="#000000" visible="true" width="40.01171875" x="3.0" y="330.4121355070024">row0<y:LabelModel><y:RowNodeLabelModel offset="3.0" /></y:LabelModel><y:ModelParameter><y:RowNodeLabelModelParameter horizontalPosition="0.0" id="row_0" inside="true" /></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
...
I just want to select < NodeLabel > Tag with the descendants("y:RowNodeLabelModelParameter").attribute("id").value = "row_0"
So far so easy.
I tried with the following code
XElement TableNode = yedFile.Descendants(y + "TableNode").FirstOrDefault();
XElement NodeLblRow = new XElement(TableNode.Elements(y + "NodeLabel")
.Where(t => t.HasElements )
.Where(x => x.Element(y + "ModelParameter")
.Element(y + "RowNodeLabelModelParameter")
.Attribute("id").Value == "row_0"
).FirstOrDefault()
);
but in the second where I get an NullReferenceException. What is missing? These are my first tries with linq and c# so it may be that I'am thinking to complicated. I think the problem occurs, because the first < NodeLabel > Tag has no child's. That's why I divided the selection in to "Where". The first one should select only the < NodeLabel > Tag's with child's an the second one should exactly match the last < NodeLabel > Tag. So far my intention.
Can someone give me a hint?
Thank you very much for your ideas and help.
For information:
I use the following namespaces
XNamespace xmlns = XNamespace.Get("http://graphml.graphdrawing.org/xmlns");
XNamespace /*xmlns:*/java = XNamespace.Get("http://www.yworks.com/xml/yfiles-common/1.0/java");
XNamespace /*xmlns:*/sys = XNamespace.Get("http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0");
XNamespace /*xmlns:*/x = XNamespace.Get("http://www.yworks.com/xml/yfiles-common/markup/2.0");
XNamespace /*xmlns:*/xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
XNamespace /*xmlns:*/y = XNamespace.Get("http://www.yworks.com/xml/graphml");
XNamespace /*xmlns:*/yed = XNamespace.Get("http://www.yworks.com/xml/yed/3");
You will get a null reference exception when you come across an element that doesn't have elements or attributes that make up your query.
By sticking with IEnumerable rather than 'exiting the monad' and making use of explicit conversions you can avoid having to do null checks, for example:
var element = yedFile.Descendants(y + "NodeLabel")
.FirstOrDefault(e => (string)e.Elements(y + "ModelParameter")
.Elements(y + "RowNodeLabelModelParameter")
.Attributes("id")
.SingleOrDefault() == "row_0");
Related
This question already has answers here:
Force XmlDocument to save empty elements with an explicit closing tag
(1 answer)
Forcing XDocument.ToString() to include the closing tag when there is no data
(2 answers)
Closed 11 months ago.
I am looking for a good approach to write a LINQ query that can preserve empty tags in XML.
Input XElement:
<LayoutDefinition >
<ScreenDefinitions>
<ScreenDefinition Monitor="1">
<SSBS>
<SSB Id="1" />
<SSB Id="2" />
</SSBS>
</ScreenDefinition>
<ScreenDefinition Monitor="2">
<SSBS>
<SSB Id="1" />
<SSB Id="2" />
</SSBS>
</ScreenDefinition>
</ScreenDefinitions>
<CustomProperties>
<Property Name="SynchronizationCollection" />
</CustomProperties>
</LayoutDefinition>
This is being process by the below method:
private static IList<XElement> ProcessLayoutDefinition(XElement layoutDefinition)
{
IList<XElement> resultLayoutDefinitions = new List<XElement>();
layoutDefinition?.XPathSelectElement($"/CustomProperties/Property[#Name=\"SynchronizationCollection\"]").Remove();
resultLayoutDefinitions.Add(layoutDefinition);
return resultLayoutDefinitions;
}
The Result should yield the below output:
<LayoutDefinition >
<ScreenDefinitions>
<ScreenDefinition Monitor="1">
<SSBS>
<SSB Id="1" />
<SSB Id="2" />
</SSBS>
</ScreenDefinition>
<ScreenDefinition Monitor="2">
<SSBS>
<SSB Id="1" />
<SSB Id="2" />
</SSBS>
</ScreenDefinition>
</ScreenDefinitions>
<CustomProperties>
</CustomProperties>
</LayoutDefinition>
But gives the below output with only <CustomProperties />
<LayoutDefinition >
<ScreenDefinitions>
<ScreenDefinition Monitor="1">
<SSBS>
<SSB Id="1" />
<SSB Id="2" />
</SSBS>
</ScreenDefinition>
<ScreenDefinition Monitor="2">
<SSBS>
<SSB Id="1" />
<SSB Id="2" />
</SSBS>
</ScreenDefinition>
</ScreenDefinitions>
<CustomProperties />
</LayoutDefinition>
Is there anyway I can force to preserve the <CustomProperties> </CustomProperties> tags although <CustomProperties /> is a correct tag.
im trying to populate a treeview from a xml file.
Image of the output: http://i.stack.imgur.com/3HSCu.png
So as you can see the parents are loaded well, but the childs (the elements) not. All the child nodes are loaded in all parent nodes. But the xml is not like that.
This is the XML code:
<?xml version="1.0" encoding="utf-8" ?>
<toolbox>
<parent id="p1" caption="All Elements" class="parent">
<element id="1" name="Button" />
<element id="2" name="Label" />
<element id="3" name="Inputfield" />
<element id="4" name="Textarea" />
<element id="5" name="Image" />
<element id="6" name="Background" />
<element id="7" name="TreeView" />
</parent>
<parent id="p2" caption="Some Elements 1" class="parent">
<element id="1" name="Button" />
<element id="2" name="Label" />
<element id="3" name="Inputfield" />
</parent>
<parent id="p3" caption="Some Elements 2" class="parent">
<element id="4" name="Textarea" />
<element id="5" name="Image" />
<element id="6" name="Background" />
<element id="7" name="TreeView" />
</parent>
</toolbox>
This is the C# code:
public void loadElements(string XML_Elements, TreeView Elements_Tree){
XmlDocument XMLDocument = new XmlDocument();
XMLDocument.Load(XML_Elements);
Elements_Tree.Nodes.Clear();
Elements_Tree.BeginUpdate();
XmlNodeList XMLParent = XMLDocument.SelectNodes("toolbox/parent");
foreach(XmlNode xmlparent in XMLParent){
//add parents
string Parent_Caption = xmlparent.Attributes["caption"].Value;
TreeNode parents = Elements_Tree.Nodes.Add(Parent_Caption);
//add childs
XmlNodeList XMLChilds = XMLDocument.SelectNodes("toolbox/parent/element");
foreach (XmlNode xmlchild in XMLChilds)
{
string Child_Name = xmlchild.Attributes["name"].Value;
parents.Nodes.Add(Child_Name);
}
}
}
You have to search for elements only within current parent element. Try that:
XmlNodeList XMLChilds = XMLDocument.SelectNodes("toolbox/parent[#caption='" + Parent_Caption + "']/element");
Or maybe even better:
XmlNodeList XMLChilds = xmlparent.SelectNodes("element");
XMLDocument.SelectNodes("toolbox/parent/element") selects all nodes that match in the document. You need to get the children of the current XmlNode, not start at the XMLDocument.
Using C# I have extracted data from Google Analytics Data API and have got it in an xmldocument. From that point I want to export it to flat file format (txt file). I am trying to use the xmlnode class to write out element attribute values within the 'entry' elements but cant do it. XML code below:
<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dxp="http://schemas.google.com/analytics/2009" xmlns:openSearch="http://a9.com/- /spec/opensearch/1.1/">
<id>https://www.googleapis.com/analytics/v2.4/data?ids=ga:xxxxxxxxx&dimensions=ga:date,ga:hostname&metrics=ga:visits,ga:newVisits,ga:visitBounceRate,ga:transactions,ga:transactionRevenue,ga:itemQuantity&start-date=2012-09-20&end-date=2012-09-26&start-index=1&max-results=1000</id>
<updated>2012-09-27T08:08:53.621Z</updated>
<title type="text">Google Analytics Data for Profile xxxxxxxxx</title>
<link rel="self" type="application/atom+xml" href="https://www.googleapis.com/analytics/v2.4/data?ids=ga:xxxxxxxxx&dimensions=ga:date,ga:hostname&metrics=ga:visits,ga:newVisits,ga:visitBounceRate,ga:transactions,ga:transactionRevenue,ga:itemQuantity&start-date=2012-09-20&end-date=2012-09-26&start-index=1&max-results=1000" />
<author>
<name>Google Analytics</name>
</author>
<generator>Google Analytics</generator>
<openSearch:totalResults>49</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>1000</openSearch:itemsPerPage>
<dxp:aggregates>
<dxp:metric name="ga:visits" type="integer" value="942258" />
<dxp:metric name="ga:newVisits" type="integer" value="393698" />
<dxp:metric name="ga:visitBounceRate" type="percent" value="26.960025810340692" />
<dxp:metric name="ga:transactions" type="integer" value="328" />
<dxp:metric name="ga:transactionRevenue" type="currency" value="427646.331187" />
<dxp:metric name="ga:itemQuantity" type="integer" value="322" />
</dxp:aggregates>
<dxp:containsSampledData>true</dxp:containsSampledData>
<dxp:dataSource>
<dxp:property name="ga:profileId" value="xxxxxxxxx" />
<dxp:property name="ga:webPropertyId" value="UA-33036832-1" />
<dxp:property name="ga:accountName" value="TCO-UK-TC.com-[thomascook.com]" />
<dxp:tableId>ga:xxxxxxxxx</dxp:tableId>
<dxp:tableName>ThomasCook UK - Analytics Extract (VP /search)</dxp:tableName>
</dxp:dataSource>
<dxp:endDate>2012-09-26</dxp:endDate>
<dxp:startDate>2012-09-20</dxp:startDate>
<entry>
<id>https://www.googleapis.com/analytics/v2.4/data?ids=ga:xxxxxxxxx&ga:date=20120920&ga:hostname=87.248.112.8&start-date=2012-09-20&end-date=2012-09-26</id>
<updated>2012-09-27T08:08:53.621Z</updated>
<title type="text">ga:date=20120920 | ga:hostname=87.248.112.8</title>
<link rel="alternate" type="text/html" href="http://www.google.com/analytics" />
<dxp:dimension name="ga:date" value="20120920" />
<dxp:dimension name="ga:hostname" value="87.248.112.8" />
<dxp:metric name="ga:visits" type="integer" value="3" />
<dxp:metric name="ga:newVisits" type="integer" value="3" />
<dxp:metric name="ga:visitBounceRate" type="percent" value="100.0" />
<dxp:metric name="ga:transactions" type="integer" value="0" />
<dxp:metric name="ga:transactionRevenue" type="currency" value="0.0" />
<dxp:metric name="ga:itemQuantity" type="integer" value="0" />
</entry>
<entry>
<id>https://www.googleapis.com/analytics/v2.4/data?ids=ga:xxxxxxxxx&ga:date=20120920&ga:hostname=alpha.thomascook.com&start-date=2012-09-20&end-date=2012-09-26</id>
<updated>2012-09-27T08:08:53.621Z</updated>
<title type="text">ga:date=20120920 | ga:hostname=alpha.thomascook.com</title>
<link rel="alternate" type="text/html" href="http://www.google.com/analytics" />
<dxp:dimension name="ga:date" value="20120920" />
<dxp:dimension name="ga:hostname" value="alpha.thomascook.com" />
<dxp:metric name="ga:visits" type="integer" value="160" />
<dxp:metric name="ga:newVisits" type="integer" value="109" />
<dxp:metric name="ga:visitBounceRate" type="percent" value="21.25" />
<dxp:metric name="ga:transactions" type="integer" value="0" />
<dxp:metric name="ga:transactionRevenue" type="currency" value="0.0" />
<dxp:metric name="ga:itemQuantity" type="integer" value="0" />
</entry>
....so on.....
In the code below I need to change it to locate the entry elements, but can't find it. Using "/entry" yields nothing.
XmlNamespaceManager xmlnsm = new XmlNamespaceManager(xmld.NameTable);
xmlnsm.AddNamespace("dxp", "http://schemas.google.com/analytics/2009");
xmlnsm.AddNamespace("openSearch", "http://a9.com/-/spec/opensearch/1.1/");
xmlnsm.AddNamespace("gd", "http://schemas.google.com/g/2005");
foreach (XmlNode xmlnd in xmld.SelectNodes("//dxp:dimension", xmlnsm))
{
DimVal = xmlnd.Attributes["value"].Value.ToString();
DimName = xmlnd.Attributes["name"].Value.Replace("ga:", "");
// ...
}
I could be missing a namespace. Can anyone please help me out?
XDocument xDoc = XDocument.Load(fileToLoad); //or XDocument.Parse(xmlString)
XNamespace dxp = "http://schemas.google.com/analytics/2009";
XNamespace ns = "http://www.w3.org/2005/Atom";
var result =
xDoc.Descendants(ns + "entry")
.Select(e => new
{
Dimension = e.Descendants(dxp + "dimension")
.ToDictionary(d => d.Attribute("name").Value, d => d.Attribute("value").Value),
Metric = e.Descendants(dxp + "metric")
.ToDictionary(d => d.Attribute("name").Value, d => d.Attribute("value").Value)
})
.ToList();
Print the result:
foreach(var entry in result)
{
foreach (var dim in entry.Dimension)
Console.WriteLine(dim.Key + " = " + dim.Value);
Console.WriteLine();
foreach (var met in entry.Metric)
Console.WriteLine(met.Key + " = " + met.Value);
Console.WriteLine("---------------");
}
If you're just interested in getting all of the dxp:dimension elements you could use
GetElementsByTagName("dimension", "http://schemas.google.com/analytics/2009")
instead of
SelectNodes("//dxp:dimension", xmlnsm)
If you're intent on using SelectNodes, I think you need another / ("///dxp:dimension").
Specifically for your case you can do:
foreach(XmlElement ele in xmld.GetElementsByTagName("element"))
{
foreach(XmlElement dim in ele.GetElementsByTagName("dimension", "http://schemas.google.com/analytics/2009")
{
// Do w/e w/ the element
}
foreach(XmlElement met in ele.GetElementsByTagName("metric", "http://schemas.google.com/analytics/2009")
{
// Do w/e w/ the element
}
}
I have the following XML document:
<database name="pressPlay">
<table name="users">
<column name="userID" type="INT" constraints="tableID_c" />
<column name="username" type="VARCHAR(50)" constraints="user_c" />
<column name="password" type="VARCHAR(50)" constraints="not_null_c" />
</table>
<table name="song">
<column name="songID" type="INT" constraints="tableID_c" />
<column name="albumID" type="INT" constraints="albumFK_c" />
<column name="artistID" type="INT" constraints="artistFK_c" />
<column name="songName" type="VARCHAR(50)" constraints="not_null_c" />
<column name="songDuration" type="VARCHAR(5)" constraints="not_null_c" />
<column name="link" type="VARCHAR(100)" />
</table>
<table name="album">
<column name="albumID" type="INT" constraints="tableID_c" />
<column name="albumName" type="VARCHAR(50)" constraints="not_null_c" />
<column name="albumGener" type="VARCHAR(50)" constraints="not_null_c" />
</table>
<table name="artist">
<column name="artistID" type="INT" constraints="tableID_c" />
<column name="artistName" type="VARCHAR(50)" constraints="not_null_c" />
</table>
<constraints>
<constraint name="tableID_c" type="unique" content="not_null" increment="auto"/>
<constraint name="user_c" type="unique" content="not_null"/>
<constraint name="not_null_c" content="not_null"/>
<constraint name="albumFK_c" type="forign_key" content="not_null" columns="album.albumID" />
<constraint name="artistFK_c" type="forign_key" content="not_null" columns="artist.artistID" />
</constraints>
</database>
now what i need is to get attributes from nodes that share a parent with a specific name attribute.
I tried to useXmlNodeList but that gives me all the nodes named column regardless of what the parents name is, i.e:
i need the name attributes from column nodes, with the parent name being users.
anyone know how to do this? i've been busting my head for a while now..
something Like that :
XmlDocument inventory = new XmlDocument();
inventory.Load("inventory.xml");
XmlNodeList elements = inventory.SelectNodes("/XMLProject/table[#name='users']/column");
foreach (XmlElement element in elements)
{
...
}
this will give you :
<column name="userID" type="INT" constraints="tableID_c" />
<column name="username" type="VARCHAR(50)" constraints="user_c" />
<column name="password" type="VARCHAR(50)" constraints="not_null_c" />
Now you can walk through each and take its attribute.
Something like this in Linq?
IEnumerable<string> names =
from x in XDocument.Load(#"project.xml").Descendants("column")
where x.Parent.Attribute("name").Value.Equals("users", StringComparison.Ordinal)
select x.Attribute("name").Value;
http://msdn.microsoft.com/en-us/library/bb387098.aspx
I would actually use LinqToXML in this case;
XDocument document = XDocument.Load("mydocument")
var table = (from n in document.Descendants("table")
where n.Attribute("name").Value == "users"
select n).Single( );
var columns = from c in table.Descendants("column")
select c.Attribute("name").Value;
That's a rough version, and I am certain there's a way to collapse them down into a single query. I find LinqToXml much easier to work with.
I have the following XML:
<funds>
<fund name="A" ITEM0="7%" ITEM1="8%" ITEM2="9%" ITEM3="10%" ITEM4="11%" ITEM5="" />
<fund name="B" ITEM0="11%" ITEM1="11%" ITEM2="13%" ITEM3="14%" ITEM4="16%" ITEM5="" />
<fund name="C" ITEM0="" ITEM1="" ITEM2="" ITEM3="" ITEM4="" ITEM5="" />
<fund name="D" ITEM0="7%" ITEM1="8%" ITEM2="9%" ITEM3="10%" ITEM4="11%" ITEM5="" />
<fund name="E" ITEM0="2%" ITEM1="3%" ITEM2="3%" ITEM3="5%" ITEM4="5%" ITEM5="" />
<fund name="F" ITEM0="" ITEM1="" ITEM2="" ITEM3="" ITEM4="" ITEM5="" />
<fund name="G" ITEM0="3%" ITEM1="3%" ITEM2="3%" ITEM3="5%" ITEM4="5%" ITEM5="" />
</funds>
<ToAppend>
<append name="A" ITEM="10" />
<append name="B" ITEM="15" />
<append name="C" ITEM="20" />
<append name="D" ITEM="20" />
<append name="E" ITEM="15" />
<append name="F" ITEM="10" />
<append name="G" ITEM="10" />
</ToAppend>
How can I loop through all of the attributes in //ToAppend/append and if 'name' is a match in //funds/fund add the attribute ITEM from //ToAppend/append to //funds/fund ?
I'm trying to append the matching items to the first list but I'm not having too much luck. Trying to get this working via C# under the 2.0 framework.
Thanks in advance!
edit:
XmlNode xmlNodeInner = root.SelectSingleNode("//ToAppend/append");
XmlNode ToBeUpdated = root.SelectSingleNode("//funds/fund");
foreach (XmlElement element in ToBeUpdated)
{
Console.WriteLine(element.InnerXml);
//Match the 'name' from xmlNodeInner to the 'name' of ToBeUpdated
//if{magic occurs here and they match}
{
element.SetAttribute("ITEM6", "value from xmlNodeInner");
}
}
I just dont know how to do the comparison inquiry to determine if A=A, or even exists, since there is no guarentee on that.
Hopefully it would come out something like:
<fund name="G" ITEM0="3%" ITEM1="3%" ITEM2="3%" ITEM3="5%" ITEM4="5%" ITEM5="" ITEM6="10"/>
This seems to work:
namespace ConsoleApplication1
{
using System;
using System.Xml;
class Program
{
static void Main( string[] args )
{
const string xml = #"
<root>
<funds>
<fund name='A' ITEM0='7%' ITEM1='8%' ITEM2='9%' ITEM3='10%' ITEM4='11%' ITEM5='' />
<fund name='B' ITEM0='11%' ITEM1='11%' ITEM2='13%' ITEM3='14%' ITEM4='16%' ITEM5='' />
<fund name='C' ITEM0='' ITEM1='' ITEM2='' ITEM3='' ITEM4='' ITEM5='' />
<fund name='D' ITEM0='7%' ITEM1='8%' ITEM2='9%' ITEM3='10%' ITEM4='11%' ITEM5='' />
<fund name='E' ITEM0='2%' ITEM1='3%' ITEM2='3%' ITEM3='5%' ITEM4='5%' ITEM5='' />
<fund name='F' ITEM0='' ITEM1='' ITEM2='' ITEM3='' ITEM4='' ITEM5='' />
<fund name='G' ITEM0='3%' ITEM1='3%' ITEM2='3%' ITEM3='5%' ITEM4='5%' ITEM5='' />
</funds>
<ToAppend>
<append name='A' ITEM='10' />
<append name='B' ITEM='15' />
<append name='C' ITEM='20' />
<append name='D' ITEM='20' />
<append name='E' ITEM='15' />
<append name='F' ITEM='10' />
<append name='G' ITEM='10' />
</ToAppend>
</root>
";
// XPath that finds all "funds/fund" nodes that have a "name" attribute with the value "{0}".
const string xpathTarget = #"//funds/fund[#name='{0}']";
// XPath that finds all "ToAppend/append" nodes that have a "name" and "ITEM" attribute.
const string xpathSourceNodes = #"//ToAppend/append[#name and #ITEM]";
var doc = new XmlDocument();
doc.LoadXml( xml );
foreach ( XmlNode sourceNode in doc.SelectNodes( xpathSourceNodes ) )
{
string name = sourceNode.Attributes[ "name" ].Value;
string item = sourceNode.Attributes[ "ITEM" ].Value;
XmlNode targetNode = doc.SelectSingleNode( String.Format( xpathTarget, name ) );
if ( null != targetNode )
{
XmlAttribute newAttribute = doc.CreateAttribute( "ITEM6" );
newAttribute.Value = item;
targetNode.Attributes.Append( newAttribute );
}
}
}
}
}