I have a XML file that has this following format:
<datasources>
<datasource name="...">
<column caption="..." name="..."> ... </column>
<column caption="..." name="..."> ... </column>
</datasource>
<datasource name="...">
<column caption="..." name="..."> ... </column>
<column caption="..." name="..."> ... </column>
</datasource>
</datasources>
...
and I want to get a caption
-name
map for columns
that meets specific criteria (that is, has an expected caption
and is a column
of an expected datasource
).
Currently I have this code but I'm not confident of it.
XmlReader reader = XmlReader.Create(new StringReader(content));
while (reader.ReadToFollowing("datasource"))
{
reader.MoveToAttribute("name");
if (reader.Value == dsName)
{
while (reader.ReadToFollowing("column"))
{
reader.MoveToAttribute("caption");
if (captions.Contains(reader.Value))
{
String cap = reader.Value;
reader.MoveToAttribute("name");
local_caps.Add(new KeyValuePair<String, String>(reader.Value, cap));
}
}
}
}
My concern is that, would the inner while
loop (looking for all column
s) read all the way towards the end of the file and hence go out of its supposed scope (within its datasource
)? If so, how should I avoid it? Thanks a lot!
This is ideal job for XPath:
doc.Load("file.xml");
var nodes = doc.SelectNodes("/datasources/datasource[@name='DS1']/column[@caption='C1']");
Of course, to get your map, you have to improve this sample a little:
string expectedDatasource = "DS1";
string expectedCaption = "C1";
string xpath = string.Format("/datasources/datasource[@name='{0}']/column[@caption='{1}']",
expectedDatasource, expectedCaption)
var local_caps = doc.SelectNodes(xpath)
.Cast<XmlElement>()
.ToDictionary(x => x.GetAttribute("name"),
x => x.GetAttribute("caption"));