C# 查找具有具有特定值c的属性的元素
我有以下Xml文件C# 查找具有具有特定值c的属性的元素,c#,xml,C#,Xml,我有以下Xml文件 <?xml version="1.0" encoding="UTF-8"?> <session xmlns="http://winscp.net/schema/session/1.0" name="test" start="2014-04-04T15:54:09.728Z"> <upload> <filename value="D:\ftp\test1.TXT" /> <destination valu
<?xml version="1.0" encoding="UTF-8"?>
<session xmlns="http://winscp.net/schema/session/1.0" name="test" start="2014-04-04T15:54:09.728Z">
<upload>
<filename value="D:\ftp\test1.TXT" />
<destination value="/in/test1.TXT" />
<result success="true" />
</upload>
<touch>
<filename value="/in/test1.TXT" />
<modification value="2014-03-27T12:45:20.000Z" />
<result success="true" />
<upload>
<filename value="D:\ftp\test2.TXT" />
<destination value="/in/test2.TXT" />
<result success="true" />
</upload>
<touch>
<filename value="/in/test2.TXT" />
<modification value="2014-03-27T12:45:20.000Z" />
<result success="false" />
</touch>
</session>
如何修改上面的代码以达到我的目的 我可能会使用XPath,因为它生成更干净的代码
var filenamesXPath = "/session/*[result[@success='true']]/filename";
var filenames = document.XPathSelectElements(filenamesXPath);
但这不仅仅是因为缺少名称空间处理而起作用——您实际需要的是以下内容
var document = XDocument.Load(file);
var namespaces = new XmlNamespaceManager(new NameTable());
namespaces.AddNamespace("ns", document.Root.GetDefaultNamespace().NamespaceName);
var filenamesXPath = "/ns:session/*[ns:result[@success='true']]/ns:filename";
var filenames = document.XPathSelectElements(filenamesXPath, namespaces);
试试这个:
var doc = XDocument.Parse(file);
XNamespace ns = "http://winscp.net/schema/session/1.0";
var elements = doc.Descendants(ns + "upload")
.Where(e =>
(string)(e.Element(ns + "result")
.Attribute("success")) == "true");
更新
由于此处更改的需求是更新的解决方案:
string xml = @"<?xml version='1.0' encoding='UTF-8'?>
<session xmlns='http://winscp.net/schema/session/1.0' name='test' start='2014-04-04T15:54:09.728Z'>
<upload>
<filename value='D:\ftp\test1.TXT' />
<destination value='/in/test1.TXT' />
<result success='true' />
</upload>
<touch>
<filename value='/in/test1.TXT' />
<modification value='2014-03-27T12:45:20.000Z' />
<result success='true' />
</touch>
<upload>
<filename value='D:\ftp\test2.TXT' />
<destination value='/in/test2.TXT' />
<result success='true' />
</upload>
<touch>
<filename value='/in/test2.TXT' />
<modification value='2014-03-27T12:45:20.000Z' />
<result success='false' />
</touch>
</session>";
var doc = XDocument.Parse(xml);
XNamespace ns = "http://winscp.net/schema/session/1.0";
var fileNames = doc.Descendants(ns + "result")
.Where(r => (string)r.Attribute("success") == "true")
.Select(e => (string)e.ElementsBeforeSelf(ns + "filename").Single().Attribute("value"));
单个用于某些方案验证。按顺序,如果每个节点触摸或上传节点中没有一个确切的文件名,您将得到异常
var xe = XElement.Parse(xml);
var ns = xe.Name.Namespace;
var filenames = from d in xe.Elements()
let success = d.Element(ns + "result").Attribute("success")
where success != null & success.Value == "true"
select d.Element(ns + "filename").Attribute("value").Value;
filenames.Dump();
这将返回结果为true的文件名列表。更新后:
void Main()
{
XElement root = XElement.Parse (
@"<?xml version='1.0' encoding='UTF-8'?>
<session name='test' start='2014-04-04T15:54:09.728Z'>
<upload>
<filename value='D:\ftp\test1.TXT' />
<destination value='/in/test1.TXT' />
<result success='true' />
</upload>
<touch>
<filename value='/in/test1.TXT' />
<modification value='2014-03-27T12:45:20.000Z' />
<result success='true' />
</touch>
<upload>
<filename value='D:\ftp\test2.TXT' />
<destination value='/in/test2.TXT' />
<result success='true' />
</upload>
<touch>
<filename value='/in/test2.TXT' />
<modification value='2014-03-27T12:45:20.000Z' />
<result success='false' />
</touch>
</session>");
var upload = from el in root.Elements("upload") select el;
var touch = from el in root.Elements("touch") select el;
// use zip to join the two lists together based on ordering to a new object
// this WON'T work if the lists are different lengths!
var filename = upload.Zip(touch,(u,t) => new { upload = u, touch = t })
.Where(item => item.upload.Descendants("result").First().Attribute("success").Value == "true"
&& item.touch.Descendants("result").First().Attribute("success").Value == "true")
.Select(item => item.upload.Descendants("filename").First().Attribute("value").Value);
foreach (string el in filename)
Console.WriteLine(el);
}
注意,我去掉了XML内容上的名称空间以使其更清晰。请随便把它放回去。如果您这样做,则必须在名称空间前面加上前缀
另外,我在Linq中这样做是因为它被要求,我认为在上传和触摸阵列上使用for循环会更快
以下是您将如何做到这一点:
var uploada = upload.ToArray();
var toucha = touch.ToArray();
List<string> filename = new List<string>();
for(int index = 0; index < uploada.Length ; index++)
{
if (uploada[index].Descendants("result").First().Attribute("success").Value == "true"
&& toucha[index].Descendants("result").First().Attribute("success").Value == "true")
filename.Add(uploada[index].Descendants("filename").First().Attribute("value").Value);
}
这对我很有用:
void Main()
{
XElement root = XElement.Parse (
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<session name=""test"" start=""2014-04-04T15:54:09.728Z"">
<upload>
<filename value=""D:\ftp\test1.TXT"" />
<destination value=""/in/test1.TXT"" />
<result success=""true"" />
</upload>
<touch>
<filename value=""/in/test2.TXT"" />
<modification value=""2014-03-27T12:45:20.000Z"" />
<result success=""true"" />
</touch>
</session>");
var filename = from el in root.Elements("upload")
where el.Descendants("result").First().Attribute("success").Value == "true"
select el.Descendants("filename").First().Attribute("value").Value;
Console.WriteLine(filename);
}
注意,我去掉了XML内容上的名称空间以使其更清晰。请随便把它放回去。如果需要,您必须在名称空间中添加前缀。OP更新了他的问题,更改了他查找文件名元素的内容,其中result success=trues。我不相信这是可能的。在连接的触摸和上载节点之间的数据中没有任何关系。订货有关系吗。请更新为requirements@Hogan是的,顺序很重要。对于同一个文件名,我们依次进行了触摸和上传。仅供参考-我使用For循环而不是Linq添加了代码。他需要同时进行上传和触摸才能获得success=true。对,注意到他进行了编辑,但我错过了这一点。触摸节点呢?@HamletHakobyan-怎么样?我的第一个解决方案检查它。第二个解决方案是一个不同的问题,请参见编辑问题的历史记录。为什么将xml更改为?@user3456466?将“全部”替换为“全部”比转到“每个”并创建它更容易。如果您正在读取一个文件,则不需要执行此操作,因为在本例中,它是一个字符串文本。
void Main()
{
XElement root = XElement.Parse (
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<session name=""test"" start=""2014-04-04T15:54:09.728Z"">
<upload>
<filename value=""D:\ftp\test1.TXT"" />
<destination value=""/in/test1.TXT"" />
<result success=""true"" />
</upload>
<touch>
<filename value=""/in/test2.TXT"" />
<modification value=""2014-03-27T12:45:20.000Z"" />
<result success=""true"" />
</touch>
</session>");
var filename = from el in root.Elements("upload")
where el.Descendants("result").First().Attribute("success").Value == "true"
select el.Descendants("filename").First().Attribute("value").Value;
Console.WriteLine(filename);
}