Как проверить значения дочерних элементов конкретного родительского элемента? - PullRequest
0 голосов
/ 06 июня 2018

У меня есть некоторые xml-файлы, в которых могут быть некоторые элементы с именем list, которые имеют атрибут list-type с 3 возможными значениями: упорядоченный, маркированный и простой .Теперь

1) для list-type="ordered", за каждым элементом list-item должен следовать элемент label, а значение label не должно начинаться с & # x

2) для list-type="bullet", за каждым элементом list-item должен следовать элемент label, а значение label должно начинаться с & #x

3) для list-type="simple", каждый элемент list-item не должен сопровождаться элементом label (простой список не имеет меток)

Я пытаюсь проверить, есть ли в файле list-item, которые не следуют приведенным выше правилам, основываясь на его непосредственном родительском элементе list

Я пробовал

string path=@"C:\temp\list.xml";
XDocument doc=XDocument.Load(path,LoadOptions.SetLineInfo);
var simplelists=doc.Descendants("list").Where(x=>x.Attribute("list-type").Value=="simple");
if (simplelists!=null)
{
    foreach (var list in simplelists)
    {
        var x=list.Descendants("list-item").Where(a=>a.Elements("label").Any()).Select(a=>((IXmlLineInfo)a).LineNumber);
        if (x!=null)
        {
            foreach (var element in x)
            {
                Console.WriteLine("Check line: "+element+", <label> not supported in SIMPLE list");
            }

        }
    }
}

var orderedlists=doc.Descendants("list").Where(x=>x.Attribute("list-type").Value=="ordered");
if (orderedlists!=null)
{
    foreach (var list in orderedlists)
    {
        var x=list.Descendants("list-item").Where(a=>!a.Elements("label").Any() || a.Element("label").Value.StartsWith(@"&#x")).Select(a=>((IXmlLineInfo)a).LineNumber);
        if (x!=null)
        {
            foreach (var element in x)
            {
                Console.WriteLine("Check line: "+element+", <label> is either missing or has unsuppoted value for list-item (ORDERED list)");
            }

        }
    }
}

var bulletlists=doc.Descendants("list").Where(x=>x.Attribute("list-type").Value=="bullet");
if (bulletlists!=null)
{
    foreach (var list in bulletlists)
    {
        var x=list.Descendants("list-item").Where(a=>!a.Elements("label").Any() || !a.Element("label").Value.EndsWith(@"&#x")).Select(a=>((IXmlLineInfo)a).LineNumber);
        if (x!=null)
        {
            foreach (var element in x)
            {
                Console.WriteLine("Check line: "+element+", <label> is either missing or has unsuppoted value for list-item (BULLET list)");
            }

        }
    }
}

Console.ReadLine();

Но это не то, что я намеревался, вот файл образца

Требуемый вывод файла образца

Check line: 6, <label> is either missing or has unsuppoted value for list-item (ORDERED list)
Check line: 13, <label> not supported in SIMPLE list
Check line: 23, <label> is either missing or has unsuppoted value for list-item (ORDERED list)

Яполучение this output

Может ли кто-нибудь помочь мне с этим?

Примечание. Могут быть вложенные элементы list внутри другого элемента list с одинаковыми или разными list-type значений.

1 Ответ

0 голосов
/ 06 июня 2018

Кажется, у вас есть 2 проблемы.Сначала вы вытягиваете все элементы списка Descendant для каждого списка, который будет включать элементы списка для вложенных списков.Вторая проблема заключается в том, что "&#x####;" в xml указывает закодированный символ, поэтому что-то вроде "&#x2022;" заменяется символом, который представляет "•" (символ маркера).Поэтому вам нужно определить, какие именно символы или какой-то диапазон являются недопустимыми для упорядоченных списков и необходимы для маркеров, поскольку любой символ может быть закодирован таким образом.Вот код, который даст желаемые результаты и значительно упростит дублирование в текущем коде.

Следует отметить, что эти символы не нужно кодировать.Вы можете заменить кодировку фактическим символом юникода в xml.Единственная причина, по которой они должны были бы быть закодированы, заключается в том, что сам файл нужно было сохранить в кодировке, которая не поддерживает символы Юникода.

XDocument doc = XDocument.Load(path, LoadOptions.SetLineInfo);
char[] invalidOrderedCharacter = new[] {'\u2022', '\u25CB' };
char[] requiredBulletCharacters = new[] {'\u2022'};
foreach (var list in doc.Descendants("list"))
{
    var listType = list.Attribute("list-type")?.Value;
    foreach (var item in list.Elements("list-item"))
    {
        var lineNumber = ((IXmlLineInfo) item).LineNumber;
        var label = item.Element("label")?.Value;
        switch (listType)
        {
            case "simple":
                if (label != null)
                {
                    Console.WriteLine(
                        "Check line: " + lineNumber + 
                        ", <label> not supported in SIMPLE list");
                }
                break;
            case "ordered":
                if (label == null || invalidOrderedCharacter.Contains(label[0]))
                {
                    Console.WriteLine(
                        "Check line: " + lineNumber + 
                        ", <label> is either missing or has unsupported value for list-item (ORDERED list)");
                }
                break;
            case "bullet":
                if (label == null || !requiredBulletCharacters.Contains(label[0]))
                {
                    Console.WriteLine(
                        "Check line: " + lineNumber + 
                        ", <label> is either missing or has unsupported value for list-item (BULLET list)");
                }
                break;
        }
    }
}
...