Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 查找具有具有特定值c的属性的元素_C#_Xml - Fatal编程技术网

C# 查找具有具有特定值c的属性的元素

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文件

<?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);

}