Чтение дочернего узла XML - PullRequest
0 голосов
/ 02 июля 2019

Я должен прочитать значение из XML в C #, основываясь на некоторых условиях. Ниже мой образец 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>

Например, если ввод оранжевый, возвращаемое значение - defaultvalue = "Orange"

Если ввод Банана, возврат будет основан на 2-м входе. Если это банан, сырой, - вернуть зеленый если это банан, пустой - вернуть желтый если это Banana, long - возвращает желтый (нет совпадения с «long», поэтому возвращает значение по умолчанию на родительском уровне).

Каков наилучший способ достичь этого.

Ответы [ 4 ]

1 голос
/ 03 июля 2019

Вот одна версия запроса:

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
1 голос
/ 02 июля 2019

Использование 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 голос
/ 02 июля 2019

Еще один пример 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

0 голосов
/ 02 июля 2019

Использование 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...