已读取XML子节点

时间:2019-07-02 17:42:16

标签: c# xml

我必须根据某些条件从C#中的XML读取值。下面是我的示例xml

<Properties>

    <prop1 Name = " Apple" Defaultvalue="red">
         <childprop Name = "special" Value="pink" >
         </childprop>
    </prop1>
    <prop1 Name = " Orange"  Defaultvalue="orange">     
    </prop1>
    <prop1 Name = "Banana" Defaultvalue="yellow">
        <childprop Name = "raw" Value="green" >
        </childprop>
        <childprop Name = "special" Value="red" >
        </childprop>
    </prop1>  
</Properties>

例如,如果输入为Orange,则返回值为defaultvalue =“ Orange”

如果输入为香蕉,则返回将基于第二输入。 如果是香蕉,生的,-返回绿色 如果是香蕉,则空白-返回黄色 如果是香蕉,则长整型-返回黄色(“长整型”不匹配,因此返回父级的默认值)。

实现此目标的最佳方法是什么。

4 个答案:

答案 0 :(得分:1)

使用Linq2xml帮助您:

var workflowXml = @"
    <Properties>
        <prop1 Name = ""Apple"" Defaultvalue=""red"">
            <childprop Name = ""special"" Value=""pink"" >
            </childprop>
        </prop1>
        <prop1 Name = ""Orange""  Defaultvalue=""orange"">     
        </prop1>
        <prop1 Name = ""Banana"" Defaultvalue=""yellow"">
            <childprop Name = ""raw"" Value=""green"" >
            </childprop>
            <childprop Name = ""special"" Value=""red"" >
            </childprop>
        </prop1>  
    </Properties>";

var xmlDoc = XDocument.Parse(workflowXml);
var xmlCurrentLevelElement = xmlDoc.Element("Properties");
var stepNumber = 1;

while (true)
{
    var options = xmlCurrentLevelElement
        .Elements()
        .Select(e => e.Attributes().FirstOrDefault(a => a.Name == "Name"))
        .Where(a => a != null)                    
        .ToArray();

    if (!options.Any())
    {
        var currentValue = xmlCurrentLevelElement
            .Attributes()
            .FirstOrDefault(a => a.Name == "Value" || a.Name == "Defaultvalue")
            ?.Value ?? "value not defined";

        Console.WriteLine($"no more options: {currentValue}");
        break;
    }

    var hints = string.Join(" or ", options.Select(a => a.Value));

    Console.WriteLine($"step {stepNumber}: input any value from '{hints}' - ");
    var value = Console.ReadLine();

    var xmlNextLevelElement = options
        .FirstOrDefault(a => a.Value == value)
        ?.Parent ?? null;

    if (xmlNextLevelElement == null)
    {
        var defaultValue = xmlCurrentLevelElement
            .AncestorsAndSelf()
            .Select(e => e.Attributes().FirstOrDefault(a => a.Name == "Defaultvalue"))
            .Where(a => a != null)
            .FirstOrDefault()
            ?.Value ?? "default value not defined";

        Console.WriteLine($"no match: {defaultValue}");
        break;
    }

    xmlCurrentLevelElement = xmlNextLevelElement;
    stepNumber++;
}

答案 1 :(得分:1)

另一个LINQ to XML示例。还有对Microsoft Docs的引用。

using System;
using System.Linq;
using System.Xml.Linq;

public class Program
{
    public static void Main()
    {

        Find("Apple");
        Find("Banana,raw");  
        Find("Banana, ");
    }

    public static void Find(string input)
    {
        var xml = @"<Properties>
            <prop1 Name = ""Apple"" Defaultvalue=""red"">
                 <childprop Name = ""special"" Value=""pink"" >
                 </childprop>
            </prop1>
            <prop1 Name = ""Orange""  Defaultvalue=""orange"">     
            </prop1>
            <prop1 Name = ""Banana"" Defaultvalue=""yellow"">
                <childprop Name = ""raw"" Value=""green"" >
                </childprop>
                <childprop Name = ""special"" Value=""red"" >
                </childprop>
            </prop1>  
        </Properties>";

        var doc = XElement.Parse(xml);

        var keywords = input.Split(',');

        XElement match = null;
        foreach (var key in keywords){
            var node = (from n in (match??doc).Descendants()
                where (string)n.Attribute("Name") == key
                select n).FirstOrDefault();
            match = node??match;
        }
        if (match != null)
            Console.WriteLine(((string) match.Attribute("Defaultvalue"))??((string)match.Attribute("Value")));
        else
            Console.WriteLine("Nothing Found.");
    }
}

.Net Fiddle中运行

答案 2 :(得分:1)

这里是一个查询版本:

var document = XDocument.Parse(xml);

var dictionaries =
    document
        .Root
            .Elements("prop1")
            .Select(prop1 => new
            {
                name = prop1.Attribute("Name").Value,
                children =
                    prop1
                        .Elements("childprop")
                        .Select(childprop => new
                        {
                            name = childprop.Attribute("Name").Value,
                            value = childprop.Attribute("Value").Value
                        })
                        .StartWith(new
                        {
                            name = "",
                            value = prop1.Attribute("Defaultvalue").Value
                        })
            })
            .ToDictionary(
                x => x.name,
                x => x.children.ToDictionary(y => y.name, y => y.value));

当我写这篇文章时:

Console.WriteLine(dictionaries["Apple"][""]);
Console.WriteLine(dictionaries["Apple"]["special"]);
Console.WriteLine(dictionaries["Banana"][""]);
Console.WriteLine(dictionaries["Banana"]["raw"]);
Console.WriteLine(dictionaries["Banana"]["special"]);   

我明白了:

red
pink
yellow
green
red

答案 3 :(得分:0)

使用 Linq

 String result = string.Empty;

var exist = xdoc.Descendants("Properties").Descendants("prop1").Attributes("Name").Where(x => x.Value.Equals(value)).FirstOrDefault();

  if (exist != null) 
  {
   XElement xElement = xdoc.Descendants("prop1").Where(x => x.Attribute("Name").Value.Equals(value).Select(x => x).FirstOrDefault();

   var childPropsExist = xElement.Elements("childprop").Any();

   if (childPropsExist) //we will be needing second input
   {

    result = xElement.Elements("childprop").Attributes("Name").Where(x => x.Value.Equals(secondInput)).FirstOrDefault().NextAttribute.Value;

   } else {
    result = exist.NextAttribute.Value; //Default value;
   }
  }

return result;