2012-07-05 119 views
3

如何解析xml文件?從xml文件獲取節點

<?xml version="1.0" encoding="UTF-8"?> 
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
<sitemap> 
    <loc>link</loc> 
    <lastmod>2011-08-17T08:23:17+00:00</lastmod> 
</sitemap> 
<sitemap> 
    <loc>link</loc> 
    <lastmod>2011-08-18T08:23:17+00:00</lastmod> 
</sitemap> 
</sitemapindex> 

我是新來的XML,我想這一點,但它似乎不工作:

 XmlDocument xml = new XmlDocument(); //* create an xml document object. 
     xml.Load("sitemap.xml"); 
     XmlNodeList xnList = xml.SelectNodes("/sitemapindex/sitemap"); 
     foreach (XmlNode xn in xnList) 
     { 
      String loc= xn["loc"].InnerText; 
      String lastmod= xn["lastmod"].InnerText; 
     } 
+0

它怎麼樣?它是否成功加載文件?如果找到兩個站點地圖元素?它是否讀取任何一個sitemap子元素?我假設這些破折號在元素標籤不在實際的xml文件中,對吧? – 2012-07-05 16:06:21

+0

xnList沒有被填充。(對不起破折號 - 沒有破折號) – Andrew 2012-07-05 16:08:11

回答

11

問題是sitemapindex元素定義了一個默認名稱空間。您需要在選擇節點時指定命名空間,否則將無法找到它們。例如:

XmlDocument xml = new XmlDocument(); 
xml.Load("sitemap.xml"); 
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable); 
manager.AddNamespace("s", "http://www.sitemaps.org/schemas/sitemap/0.9"); 
XmlNodeList xnList = xml.SelectNodes("/s:sitemapindex/s:sitemap", manager); 

通常來說,使用XmlNameSpaceManager時,你可以離開前綴爲空字符串指定您希望該命名空間是默認的命名空間。所以,你會覺得你可以做這樣的事情:

// WON'T WORK 
XmlDocument xml = new XmlDocument(); 
xml.Load("sitemap.xml"); 
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable); 
manager.AddNamespace("", "http://www.sitemaps.org/schemas/sitemap/0.9"); //Empty prefix 
XmlNodeList xnList = xml.SelectNodes("/sitemapindex/sitemap", manager); //No prefixes in XPath 

但是,如果你嘗試的代碼,你會發現,它不會找到任何匹配的節點。原因是在XPath 1.0(這是XmlDocument實現的)中,當沒有提供名稱空間時,它始終使用空名稱空間,而不是默認名稱空間。因此,如果您在XmlNamespaceManager中指定默認名稱空間,則無關緊要,XPath不會使用它。引述從Official XPath Specification有關段落:

的QName在節點測試擴展成使用 命名空間聲明從表達式上下文中的擴展名。這與 中的元素類型名稱完全相同 擴展方式除了不使用用xmlns聲明的默認名稱空間外:如果012xxQName沒有前綴,則名稱空間URI爲空 (這個 與擴展屬性名稱的方式相同)。如果 QName的前綴在 表達式上下文中沒有名稱空間聲明,則會出錯。

因此,當您正在閱讀的元素屬於某個命名空間時,無法避免將命名空間前綴放入XPath語句中。但是,如果您不想將名稱空間URI放入代碼中,則可以使用XmlDocument對象返回根元素的URI,在這種情況下,它是您想要的。例如:

XmlDocument xml = new XmlDocument(); 
xml.Load("sitemap.xml"); 
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable); 
manager.AddNamespace("s", xml.DocumentElement.NamespaceURI); //Using xml's properties instead of hard-coded URI 
XmlNodeList xnList = xml.SelectNodes("/s:sitemapindex/s:sitemap", manager); 
+0

你的例子工作正常!謝謝。有沒有辦法在不指定名稱的情況下進入默認名稱空間? – Andrew 2012-07-05 16:42:08

+1

@Andrew很高興幫助!我添加了一些關於命名空間的附加信息給我的答案。 – 2012-07-05 18:30:04

+0

+1很好的信息。很高興知道。 – SysDragon 2013-07-19 12:28:23

0

網站地圖有2個個子節點 「祿」 和 「的lastmod」。您正在訪問的節點是「名稱」和「網址」。這就是爲什麼你沒有得到任何結果。同樣在你的XML文件中,最後一個sitemap標籤沒有正確關閉,請嘗試xn [「loc」]。InnerText,看看你是否得到了預期的結果。

+0

正如OP在他的評論中所說的,問題是沒有讀取名稱和URL,問題是'xnList'是空的。 – 2012-07-05 16:17:46

+0

明白了Steve。我的第二點是XML文件有一個標籤'站點地圖',它沒有關閉。因此,當列表由站點地圖標記填充時,由於最後一個站點地圖標記而出現錯誤。 – user1071979 2012-07-05 16:31:36

+0

我很抱歉,但是XML文件是正確的,我修正了上面的示例。上面的SteveDog的例子工作。 – Andrew 2012-07-05 16:40:55

-1

我肯定會使用LINQ to XML而不是基於舊的基於XmlDocument的XML API。你可以使用下面的代碼完成你正在尋找的東西。注意,我改變了我試圖獲得'loc'和'lastmod'值的元素的名稱,因爲這是你的示例XML('name'和'url'不存在)中的內容:

XElement element = XElement.Parse(XMLFILE); 
     IEnumerable<XElement> list = element.Elements("sitemap"); 
     foreach (XElement e in list) 
     { 
      String LOC= e.Element("loc").Value; 
      String LASTMOD = e.Element("lastmod").Value; 
     }