C# поиск и замена атрибутов XML
У меня есть выходной XML-файл со следующей структурой
<OFBM time="10:32" date="06.10.2017" saveName="Unnamed save">
<folder name="file:///C:/Users/AD/Downloads" />
<folder name="file:///C:/Users/AD/Desktop/t" />
<folder name="file:///C:/ProgramData/OFBM" />
</OFBM>
Комбинация даты и времени уникальна. Как на основе времени и даты я могу проанализировать значение, которое изменит атрибут saveName?
Как лучше всего это сделать?
Вот что я написал
public void saveNames(string time, string date, string folderName)
{
if(folderName == "Unnamed save")
return;
XElement root = XElement.Load(pathToXml);
IEnumerable<XElement> address =
from el in root.Elements("OFBM")
where (string)el.Attribute("time") == time
where (string)el.Attribute("date") == date
select el;
foreach (XElement el in address.Elements("saveName"))
{
el.ReplaceWith(folderName);
}
root.Save(pathToXml);
}
Тоже пробовал это
// <OFBM time="10:30" date="06.10.2017" saveName="Unnamed save">
XPathDocument document = new XPathDocument(pathToXml);
//The XPathNavigator object is used for read-only XPath queries. The XPath queries may return a resulting value or many nodes
XPathNavigator documentNav = document.CreateNavigator();
// This expression uses standard XPath syntax.
string filter = "@*";
XPathNodeIterator NodeIter = documentNav.Select(filter);
while (NodeIter.MoveNext())
{
Console.WriteLine("Save: {0}", NodeIter.Current.Value);
};
ПС. Однако мой код ничего не меняет.
2 ответов:
Если у вас есть только фрагмент Xml (как в вашем примере) , вы можете использовать этот код:
if (root.Attribute("time").Value == time && root.Attribute("date").Value == date && root.Attribute("saveName") != null) { root.Attribute("saveName").Value = folderName; }
rootэто ваш элементOFBM ... поэтомуroot.Element("OFBM")равно нулюПравка:
Если у вас есть xml с несколькимиOFBM элементами (я думаю, что у вас есть более одного). Используйте это:
var address = root.Elements("OFBM").Where(element => element.Attribute("time").Value == time && element.Attribute("date").Value == date && element.Attribute("saveName") != null); foreach (XElement el in address) { el.Attribute("saveName").Value = folderName; }Пример Xml:
<root> <OFBM time="10:32" date="06.10.2017" saveName="Unnamed save"> <folder name="file:///C:/Users/AD/Downloads" /> <folder name="file:///C:/Users/AD/Desktop/t" /> <folder name="file:///C:/ProgramData/OFBM" /> </OFBM> <OFBM time="10:42" date="06.10.2017" saveName="Unnamed save"> <folder name="file:///C:/Users/AD/Downloads" /> <folder name="file:///C:/Users/AD/Desktop/t" /> <folder name="file:///C:/ProgramData/OFBM" /> </OFBM> </root>
Есть пара проблем:
XElement root = XElement.Load(pathToXml);Здесь,
rootестьOFBM. Поэтому при запросеroot.Elements()возвращаемые элементы будут дочерними по отношению кOFBM, т. е. 3folderэлемента. Это означает, что ваш запросroot.Elements("OFBM")никогда не вернет никаких элементов.Во-вторых,
ReplaceWithзаменит весь элемент некоторым текстом. Вы хотите задать значение атрибутаsaveName.Этот код будет работать:
var root = XElement.Load("path/to/file.xml"); if ((string) root.Attribute("time") == "10:32" && (string) root.Attribute("date") == "06.10.2017") { root.SetAttributeValue("saveName", "new folder name"); } root.Save("path/to/file.xml");
Comments