首页 > 解决方案 > 如何检查特定父元素的子元素的值?

问题描述

我有一些 xml 文件,其中可能有一些名为 的元素list,它的属性list-type具有 3 个可能的值,分别是ordered、bulletsimple。现在

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)

我越来越这个输出

谁能帮我这个?

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

标签: c#xml-parsinglinq-to-xml

解决方案


看来你有2个问题。首先,您要为每个列表提取所有 Descendant 列表项,其中将包括嵌套列表的列表项。第二个问题是"&#x####;"in xml 表示编码字符,因此类似"&#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;
        }
    }
}

推荐阅读