导航XML节点的问题。仅在特定元素时才需要子节点

时间:2015-12-04 18:41:21

标签: c# xml xpath

我第一次使用XML,并且我有一个XML文件,用于包含州,城市和众议院号码元素的地址 这是我的XML文件的缩写版本,对不起它已经很久了。

<?xml version="1.0" encoding="UTF-8"?>
    <Locations>
       <State>
          Ohio OH
          <City>
             Cincinnati
             <Street>
                Walnut Street
                <Number>650</Number>
                <Number>600</Number>
                <Number>700</Number>
                <Number>414</Number>
             </Street>
             <Street>
                Woolper Ave
                <Number>110</Number>
             </Street>
             <Street>
                Worth Ave
                <Number>2022</Number>
             </Street>
             <Street>
                Madison Rd
                <Number>3081</Number>
             </Street>
             <Street>
                Wasson Rd
                <Number>3376</Number>
             </Street>
             <Street>
                Wooster Pike
                <Number>6906</Number>
                <Number>7453</Number>
             </Street>
             <Street>
                Woodcroft Dr
                <Number>7314</Number>
             </Street>
             <Street>
                Pike St
                <Number>316</Number>
             </Street>
             <Street>
                Wocher Ave
                <Number>119</Number>
             </Street>
             <Street>
                Fairfield Ave
                <Number>3244</Number>
             </Street>
             <Street>
                Glen Este-Withamsville Rd
                <Number>4450</Number>
             </Street>
             <Street>
                Linwood Ave
                <Number>3151</Number>
                <Number>3209</Number>
             </Street>
             <Street>
                Newtown Rd
                <Number>3811</Number>
             </Street>
             <Street>
                Round Bottom Rd
                <Number>3700</Number>
             </Street>
             <Street>
                Main St
                <Number>7849</Number>
             </Street>
             <Street>
                Eastgate Blvd
                <Number>4501</Number>
             </Street>
          </City>
          <City>
             New Richmond
             <Street>
                front
                <Number />
             </Street>
          </City>
          <City>
             Batavia
             <Street>
                <Number />
             </Street>
          </City>
          <City>
             Bethel
             <Street>
                <Number />
             </Street>
          </City>
          <City>
             Amelia
             <Street>
                <Number />
             </Street>
          </City>
          <City>
             Williamsburg
             <Street>
                <Number />
             </Street>
          </City>
          <City>
             Dayton
             <Street>
                <Number />
             </Street>
          </City>
          <City>
             Columbus
             <Street>
                <Number />
             </Street>
          </City>
          <City>
             Cleveland
             <Street>
                <Number />
             </Street>
          </City>
          <City>
             Washington Court House
             <Street>
                <Number />
             </Street>
          </City>
       </State>
       <State>
          Alabama AL
          <City>
             <Street>
                <Number />
             </Street>
          </City>
       </State>
       <State>
          Montana MT
          <City>
             <Street>
                <Number />
             </Street>
          </City>
       </State>
       <State>
          Alaska AK
          <City>
             <Street>
                <Number />
             </Street>
          </City>
       </State>
       <State>
          Nebraska NE
          <City>
             <Street>
                <Number />
             </Street>
          </City>
       </State>
       <State>
          Arizona AZ
          <City>
             <Street>
                <Number />
             </Street>
          </City>
       </State>
    </Locations>

无论如何,我正在尝试添加俄亥俄州OH元素内的城市。

我尝试过使用System.Xml,System.Xml.Linq和System.Xml.XPath;

Xpath显示了最大的承诺,但是我无法确定是否可以返回属于特定元素的元素。例如包含“Ohio OH”的State Element中的所有City元素。我完全有可能将属性附加到这些元素上。

我的计划是将状态加载到列表框中,然后根据所选状态显示另一个列表框中的向下树的城市,依此类推。

我现在添加状态的代码如下。这很好,因为它只有1级深。

XmlNodeList nodeList;
        XmlNode root = doc.DocumentElement;
        nodeList = root.SelectNodes("//Locations/State");

        foreach (XmlNode state in nodeList)
        {
            Listbox1.Items.Add(state.FirstChild.InnerText);
        }

我认为我的问题在于处理使用FirstChild,NextSibling的问题。

感谢您的帮助。希望我能很好地解释我的问题。

2 个答案:

答案 0 :(得分:1)

您可以使用[]过滤元素,因此只能获取State - 元素文本包含&#39; Ohio OH&#39;的元素,执行:

/Locations/State[contains(text(), 'Ohio OH')]

要获取这些元素的City - 孩子,请执行以下操作:

/Locations/State[contains(text(), 'Ohio OH')]/City

contains() - 函数记录在XPath specification

答案 1 :(得分:0)

试试这个。它只返回带有子项,空格和返回的名称部分。如果纽约州包含俄亥俄州街,我更新了实现州将匹配的代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            XDocument doc = XDocument.Load(FILENAME);
            var result = doc.Descendants("State").Where(x => x.Nodes().FirstOrDefault().ToString().Trim().Contains("Ohio")).Elements("City").Select(y => new {
                City = y.Nodes().FirstOrDefault().ToString().Trim(),
                Streets = y.Elements("Street").Select(z => new {
                    StreeName = z.Nodes().FirstOrDefault().ToString().Trim(),
                    Numbers = z.Elements("Number").Select(a => new {
                        Number = a.Value
                    }).ToList()
                }).ToList()
            }).ToList();

        }
    }
}