2012-09-26 87 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("//*")を使用すると、すべてのノードが正常に返されます。ここで私の問題は何ですか?

私はまた、このような

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

何もかかわらず、単一のノードを取得するために表示されないなどというXPathクエリに多くのバリエーションを試してみました。理想的には、ノードにApplicationノードがすべて含まれているようにしたい

+2

タイトルはXDocumentについて語りますが、コードではXmlDocumentが使用されています。 XMLにLINQを使っているのであれば、Descendantsを使うことをお勧めします... LINQ to XMLはオプションですか? –

+0

@JonSkeet悲しいことに、私たちは.Net 2.0をターゲットにしているのでLinqをXMLに使うことはできません。しかし、私はXmlDocumentを置くことを意味しました。私はいつも2つを混乱させます – Earlz

答えて

27

特にxml名前空間を使用する必要があります。ここにあなたのコードだ

 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

最初の1つは「表現はノードセットに評価されなければなりません」 – Earlz

+0

更新されたサンプル - 不足していました* – aiodintsov

+0

ああ、それは今動作します。偶然、これを行うよりクリーンな方法がありますか?私はXPathで名前空間を扱ったことがありませんので、私は '/ Applications/Application'のようにシンプルできれいなものを使用しています。 – Earlz

2

をあなたはこの

を読む必要があります:

このコードもうまくいくかもしれあなたのケースで

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

を考えます

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

私はそれを読んだ:)私は名前空間のないXMLファイルと比較してXPathクエリを大幅に変更することに気がつかなかった。 – 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は別のオプションです。

*)。あなたの特定のサンプルには、2つの名前空間 "default"(デフォルトの接頭辞は空の名前空間と同じではないことに注意してください)と "build"があります。したがって、名前空間マネージャーを定義するときには、名前空間のそれぞれに接頭辞を指定する必要があります(どちらのノードも対象にする必要がある場合)。接頭辞は任意の文字列(接頭辞は有効ですが空ではありません)でもかまいません。私。 「デフォルト」名前空間には「a」を使用し、XMLで「ビルド」にマップされた名前空間には「bar」を使用します。

+0

Heh、それは奇妙だ。このコードでは、 "名前空間マネージャーまたは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']" 

が動作します。

関連する問題