如何检查特定父元素的子元素的值?

How to check values of child elements of specific parent element?

我有一些 xml 文件,其中可能有一些名为 list 的元素,其属性 list-type 具有 3 个可能的值,如 ordered,bullet 简单 。 现在

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

检查文件中是否有任何 list-item 不遵循上述规则

我试过了

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

但它没有按照我的意图进行,这里是 sample file

样本文件的期望输出是

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)

我得到

谁能帮我解决这个问题?

注意:可以在具有相同或不同 list-type 值的另一个 list 元素中嵌套 list 个元素。

您似乎有 2 个问题。首先,您将提取每个列表的所有后代列表项,其中将包括嵌套列表的列表项。第二个问题是 xml 中的 "&#x####;" 表示编码字符,因此像 "&#x2022;" 被它代表的字符 "•" (项目符号字符)替换。因此,您需要确定哪些确切字符或某些范围对于有序列表无效并且对于项目符号是必需的,因为任何字符都可以这样编码。下面的代码将提供您想要的结果并简化当前代码中的大量重复。

需要注意的是,这些字符不必进行编码。您可以用 xml 中的实际 unicode 字符替换编码。它们需要编码的唯一原因是文件本身需要以不支持 unicode 字符的编码保存。

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;
        }
    }
}