简体   繁体   English

根据属性查找 XML 元素

[英]Find XML element based on attributes

Assume I have this XML假设我有这个 XML

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" mergefield="blah">

    <filter blah="rrr"></filter>
    <filter blah="qqq"></filter>
    <filter blah="www"></filter>

</hibernate-mapping>

Each time targetElement should be assigned if its corresponding attribute name is found in sourceElement每次targetElement如果其对应的属性名称中找到应分配sourceElement

namespace Test

{
    class Program
    {
    static void Main(string[] args)
    {

        var path = (@"PATHFORXML");
        XElement target = XElement.Load(path);
        XElement source = XElement.Load(path);

        foreach (var sourceElement in source.Elements())
        {


            XElement targetElement = target.Elements().SingleOrDefault(
                    t =>
                        String.Equals(
                            (string)t.Attribute(GetMergeAttr(target)),
                            (string)sourceElement.Attribute(GetMergeAttr(source)),
                            StringComparison.InvariantCultureIgnoreCase)
                  );
        }


        Console.ReadLine();
    }

    private static string GetMergeAttr(XElement element)
    {
        return (string)element.Attribute("mergefield");
    }
}

} }

PROBLEM问题

Now I have a situation where mergefield can be either "blah" or "blahblah" .现在我的情况是mergefield可以是"blah""blahblah" So I want above code to work same way for this XML:所以我希望上面的代码对这个 XML 以相同的方式工作:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" mergefield="blah,blahblah">

    <filter blah="rrr"></filter>
    <filter blahblah="qqq"></filter>
    <filter blahblah="www"></filter>

</hibernate-mapping>

Aka, either of mergefields should work Aka,任何一个mergefields都应该工作

My attempts are those.我的尝试就是这些。 GetMergeAttr should become this: GetMergeAttr应该变成这样:

private static string[] GetMergeAttr(XElement element)
        {
            var f = ((string)element.Attribute("mergefield")).Split(',');
            return f;
        }

and I can't finish query part我无法完成查询部分

XElement targetElement = target.Elements().SingleOrDefault(
                        t =>
                            String.Equals(
                                (string)t.Attribute(GetMergeAttr(target).SingleOrDefault(u=> ?????????)),
                                (string)sourceElement.Attribute(GetMergeAttr(source).SingleOrDefault(u => ?????????))
                                )
                      );

This works, but what if I have more than 3 mergefield values (I need to update this query to accept any number of mergefields, not just 2) :这是有效的,但是如果我有 3 个以上的合并字段值(我需要更新此查询以接受任意数量的合并字段,而不仅仅是 2 个)怎么办

            XElement targetElement = target.Elements().SingleOrDefault(
                    t =>
                        String.Equals(
                            (string)t.Attribute(GetMergeAttr(target).Last())?? (string)t.Attribute(GetMergeAttr(target).First()),
                            (string)sourceElement.Attribute(GetMergeAttr(source).Last()) ?? (string)sourceElement.Attribute(GetMergeAttr(source).First())
                            )
                  );

Update based on comments.根据评论更新。

I assume following is what you require我假设以下是您所需要的

XElement target = XElement.Parse(txml);
XElement source = XElement.Parse(sxml);
var targetMergeAttrs = GetMergeAttr(target);
var sourceMergeAttrs = GetMergeAttr(source);

foreach (var sourceElement in source.Elements())
{
        foreach(var mergeField in sourceMergeAttrs)
        {

            if(sourceElement.Attributes().Any(x=>x.Name.LocalName.Equals(mergeField)) &&
            target.Elements()
                  .Any(x=>x.Attributes()
                                      .Where(c=>c.Name.LocalName == mergeField 
                                      && targetMergeAttrs.Contains(mergeField)
                                      && c.Value == (string)sourceElement.Attribute(mergeField)).Any()
                                      ))
            {
                XElement targetElement = target.Elements()
                  .FirstOrDefault(x=>x.Attributes()
                                      .Where(c=>c.Name.LocalName == mergeField 
                                      && targetMergeAttrs.Contains(mergeField)
                                      && c.Value == (string)sourceElement.Attribute(mergeField)).Any()
                                      );
                // Do work with targetElement 
                break;
            }

        }
}

I am not sure what you want to achieve but does this code behave as expected?我不确定您想要实现什么,但是此代码的行为是否符合预期?

using System;
using System.Linq;
using System.Xml.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var path = (@"PATH");
            XElement target = XElement.Load(path);
            XElement source = XElement.Load(path);
            var mergefields = GetMergeAttr(target);

            foreach (var sourceElement in source.Elements())
            {
                var targetElements = from mergefield in mergefields
                                     select target.Elements().SingleOrDefault(t => 
                                         {
                                             if (t.Attribute(mergefield) == null || sourceElement.Attribute(mergefield) == null)
                                             {
                                                 return false;
                                             }

                                             return String.Equals(
                                             t.Attribute(mergefield).Value,
                                             sourceElement.Attribute(mergefield).Value,
                                             StringComparison.InvariantCultureIgnoreCase);
                                         }
                                     );
                foreach (var element in targetElements)
                {
                    Console.WriteLine(element);
                }
            }

            Console.ReadLine();
        }

        private static string[] GetMergeAttr(XElement element)
        {
            string mergefield = (string)element.Attribute("mergefield");
            return mergefield.Split(',');
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM