2012-09-26 17 views
11

我想解析一個XML文檔。有問題的文檔是一個AppxManifest文件。無法獲取XmlDocument.SelectNodes來檢索我的任何節點?

一個例子文件看起來是這樣的:

<?xml version="1.0" encoding="utf-8"?> 
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:build="http://schemas.microsoft.com/developer/appx/2012/build" IgnorableNamespaces="build"> 
    <Identity Name="uytury" Publisher="hygj" Version="1.0.0.12" ProcessorArchitecture="neutral" /> 
    <Properties> 
    <DisplayName>jhjj</DisplayName> 
    <PublisherDisplayName>bhhjb</PublisherDisplayName> 
    <Logo>Assets\StoreLogo.png</Logo> 
    </Properties> 
    <Prerequisites> 
    <OSMinVersion>6.2.1</OSMinVersion> 
    <OSMaxVersionTested>6.2.1</OSMaxVersionTested> 
    </Prerequisites> 
    <Resources> 
    <Resource Language="EN" /> 
    </Resources> 
    <Applications> 
    <Application Id="App" Executable="gfg.exe" EntryPoint="gfg.App"> 
     <VisualElements DisplayName="fdsf" Logo="Assets\Logo.png" SmallLogo="Assets\SmallLogo.png" Description="gfdsg" ForegroundText="light" BackgroundColor="#2672EC"> 
     <DefaultTile ShowName="allLogos" WideLogo="Assets\WideLogo.png" ShortName="gfdsg" /> 
     <SplashScreen Image="Assets\SplashScreen.png" BackgroundColor="#2672EC" /> 
     <InitialRotationPreference> 
      <Rotation Preference="portrait" /> 
      <Rotation Preference="landscape" /> 
      <Rotation Preference="portraitFlipped" /> 
      <Rotation Preference="landscapeFlipped" /> 
     </InitialRotationPreference> 
     </VisualElements> 
     <Extensions> 
     <Extension Category="windows.search" /> 
     <Extension Category="windows.shareTarget"> 
      <ShareTarget> 
      <DataFormat>Text</DataFormat> 
      </ShareTarget> 
     </Extension> 
     </Extensions> 
    </Application> 
    </Applications> 
    <build:Metadata> 
    <build:Item Name="TargetFrameworkMoniker" Value=".NETCore,Version=v4.5" /> 
    <build:Item Name="VisualStudio" Version="11.0" /> 
    <build:Item Name="OperatingSystem" Version="6.2.9200.16384 (win8_rtm.120725-1247)" /> 
    <build:Item Name="Microsoft.Build.AppxPackage.dll" Version="11.0.50727.1" /> 
    <build:Item Name="Microsoft.Windows.UI.Xaml.Build.Tasks.dll" Version="11.0.50727.1" /> 
    </build:Metadata> 
</Package> 

我嘗試分析它像這樣:

var xml=new XmlDocument(); 
xml.Load(myfile); 
var mgr=new XmlNamespaceManager(xml.NameTable); 
mgr.AddNamespace("", "http://schemas.microsoft.com/appx/2010/manifest"); 
var nodes=xml.SelectNodes("Applications"); 

然而,當我執行此,nodes永遠不會包含任何東西。儘管如此,XML文檔已加載。按照預期使用SelectNodes("//*")返回每個節點。我這裏有什麼問題?

我也嘗試了許多變化對XPath查詢如

  • /Package/Applications/Application
  • Applications/Application
  • Applications/*

沒有出現,雖然獲取單個節點。理想情況下,我希望節點包含所有Application節點

+2

您的標題討論XDocument,但您的代碼使用XmlDocument。如果你真的*使用LINQ to XML,我只是建議使用Descendants ...是LINQ to XML的一個選項嗎? –

+0

@JonSkeet可悲的是,我們不能使用Linq到XML,因爲我們的目標是.Net 2.0。但是我打算把XmlDocument。我總是得到兩個困惑 – Earlz

回答

27

您必須專門使用xml命名空間來選擇它們。考慮

"//*[local-name()='Applications']/*[local-name()='Application']"  
你的情況

這段代碼也可以工作得很好:

 var doc = new XmlDocument(); 
     doc.LoadXml(xml); 
     var nsmgr = new XmlNamespaceManager(doc.NameTable); 
     nsmgr.AddNamespace("a", "http://schemas.microsoft.com/appx/2010/manifest"); 
     var nodes = doc.SelectNodes("//a:Applications/a:Application",nsmgr); 
+0

對於第一個我得到「表達式必須評估爲一個節點集」 – Earlz

+0

更新的示例 - 缺少* – aiodintsov

+0

啊,現在的作品。偶然有一種更乾淨的方式來做到這一點?我從來沒有用XPath處理過命名空間,所以我使用了'/ Applications/Application'這樣簡單而乾淨的工作 – Earlz

2

您可能需要閱讀本

這是你的代碼:

var xml = new XmlDocument(); 
xml.Load("myXMLFile1.xml"); 
var mgr = new XmlNamespaceManager(xml.NameTable); 
mgr.AddNamespace("", "http://schemas.microsoft.com/appx/2010/manifest"); 
XmlNode root = xml.DocumentElement; 
var nodes = root.SelectNodes("//*[local-name()='Applications']/*[local-name()='Application']"); 
+0

我沒有讀過:)我只是沒有意識到它會改變我的XPath查詢,從根本上比較沒有名稱空間的XML文件 – Earlz

7

您需要爲NamespaceManager和XPath中的名稱空間指定前綴。請注意,除了您的XPath和您的名稱空間管理器*之外,前綴不需要匹配任何內容。

var xml=new XmlDocument(); 
xml.Load(myfile); 
var mgr=new XmlNamespaceManager(xml.NameTable); 
mgr.AddNamespace("a", "http://schemas.microsoft.com/appx/2010/manifest"); 
mgr.AddNamespace("bar", "http://schemas.microsoft.com/developer/appx/2012/build"); 
var nodes=xml.SelectNodes("//a:Applications", mgr); 

正如其他答案所指出的那樣,接受任何命名空間的XPath是另一種選擇。

*)I.e.在您的特定示例中,有2個名稱空間「default」(請注意,默認前綴與空名稱空間不同)和「build」。所以當你定義你的命名空間管理器時,你需要爲每個命名空間指定一個前綴(如果你需要在兩者中都定位節點),但前綴可以是任意字符串(對前綴有效但不爲空)。即對於映射到XML中的「build」的名稱空間,使用「a」作爲「默認」名稱空間和「bar」。

+0

嘿,這很奇怪。通過這段代碼,我得到了「命名空間管理器或XsltContext需要。這個查詢有一個前綴,變量或用戶定義的函數」,這對我來說沒有任何意義,因爲我有一個命名空間管理器? – Earlz

+1

我認爲'// a:Applications'或'a:Package/a:Applications',因爲該節點不直接位於根目錄下。 – MiMo

+1

命名空間管理器應該傳遞給'SelectNodes':'SelectNodes(「// a:Applications」,mgr);' – MiMo

0

不是在這種特殊情況下,但通常情況下,如果實際XML中的名稱空間URN與用於向名稱空間管理器添加名稱空間的名稱空間不完全相同(例如:缺少尾部斜槓)以及前綴在XPath中指定時,查詢可能會返回null

如果XML命名空間URN是不可靠的,語法

"//*[local-name()='tag']" 

會工作。