使用循环查找具有类似节点名称的节点值

时间:2014-09-17 05:16:18

标签: c# xml

我正在尝试使用Selenium和C#实现测试,该测试读取XML配置文件并执行自动测试。我的XML如下所示:

<appSettings>
  <add key="Url" value=" http://book.jetstar.com/"/>

  <!--Id's or Xpath-->  <!--LOCATOR-->
  <add key="Origin" value="somevalue"/>
  <add key="Destination" value="somevalue"/>
  <add key="Adult" value ="somevalue" />
  <add key="SearchFlights" value ="somevalue"/>

  <!--Controls-->
  <add key="OriginCtrl" value=" Input"/>
  <add key="DestinationCtrl" value=" Input"/>
  <add key="AdultCtrl" value=" Select"/>
  <add key="SearchFlightsCtrl " value=" Button"/>

</appSettings> 

该过程旨在:

  1. 读取XML文件并获取“Key”和“value”的值,通过检查“Key”是否具有文本“Ctrl”来确定节点是“Locator”还是“Controller”。

  2. 确定定位器后,循环遍历XML并找到相对“控制器” 例如:定位器“Origin”有一个名为“OriginCtrl”的控制器。

    3.获取此控制器的“值”并通过其他方法解析。

  3. 现在我对找到对象的相对控制器的过程很困惑。我使用下面的代码来获取节点的值,但是在找到Locator时找不到“继续”循环的方法并搜索它的Controller。

     xmlDoc.Load(filename);
                XmlNodeList elemList = xmlDoc.GetElementsByTagName("add");
    
                for (int i = 0; i < elemList.Count; i++)
                {
                      string keyname = elemList[i].Attributes["key"].Value;
                      string keyvalue = elemList[i].Attributes["value"].Value;
                }
    

    有关如何实施此流程的任何提示或建议都将受到高度赞赏。

4 个答案:

答案 0 :(得分:0)

由于您使用XmlDocumentSelectNodes()SelectSingleNode()的组合以及正确的XPath参数非常便于选择XML文档的任何特定部分,例如:

xmlDoc.Load(filename);
//select all <add> nodes having key attribute
XmlNodeList elemList = xmlDoc.SelectNodes("//add[@key]");
foreach(XmlNode add in elemList)
{
    string keyname = add.Attributes["key"].Value;
    string keyvalue = add.Attributes["value"].Value;

    //if current node is not a controller, get corresponding controller
    if (!keyname.EndsWith("Ctrl"))
    {
        string xpath = String.Format("../add[contains(@key, '{0}Ctrl')]", keyname);
        var controller = add.SelectSingleNode(xpath);
        var value = "";
        if(controller != null)
        {
            value = controller.Attributes["value"].Value;
            Console.WriteLine(value);
        }
    }
}

答案 1 :(得分:0)

我能想到的最好的是,使用xsd.exe生成相应的类

之后,将只有两个具有键值对的词典。

答案 2 :(得分:0)

尝试使用此代码进行测试和运作

说明:

首先检查定位器,然后检查定位器值,搜索指定的控制器并将其值赋给'value2'

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(filename);
        XmlNodeList elemList = xmlDoc.GetElementsByTagName("add");
        for (int i = 0; i < elemList.Count; i++)
        {
            string keyname = elemList[i].Attributes["key"].Value;
            string keyvalue = elemList[i].Attributes["value"].Value;
            if (!keyname.EndsWith("Ctrl"))
            {
                for(int j = 0 ; j < elemList.Count; j++)
                {
                    bool xmlnode = elemList[j].Attributes["key"]
                                   .Value.Equals(keyname + "Ctrl");
                    if (xmlnode)
                    {
                        string value2 = elemList[j].Attributes["value"].Value;
                    }
                }
            }
        }

答案 3 :(得分:0)

以下是您可以做的事情。使用这种方法,您将只遍历半文件。因此,它会比其他方式快得多。

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

public class Program
{
    public static void Main()
    {
        XDocument xDocument =
            XDocument.Load(@"C:\Visual Studio\Projects\ConsoleApplication3\ConsoleApplication3\config.xml");

        if (xDocument != null)
        {
            var locators = from x in xDocument.Descendants("add")
                where !x.Attribute("key").Value.EndsWith("Ctrl")
                select x;

            if (locators.Any())
            {
                foreach (var locator in locators)
                {
                    var controller = from c in xDocument.Descendants("add")
                        where
                            c.Attribute("key")
                                .Value.Equals(locator.Attribute("key").Value + "ctrl",
                                    StringComparison.CurrentCultureIgnoreCase) 
                        select c;

                    if (controller.Any())
                    {
                        Console.WriteLine(controller.First().Attribute("value"));
                    }

                }


            }
        }
    }
}