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

时间:2018-06-06 02:23:35

标签: c# xml-parsing linq-to-xml

我有一些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(简单列表没有标签&#39; s)< / p>

我尝试检查文件中是否存在基于其直接父元素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();

但它没有按照我的意图行事,这里是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)

我得到了this output

任何人都可以帮我吗?

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

1 个答案:

答案 0 :(得分:2)

您似乎有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;
        }
    }
}