Не удается получить XmlDocument.SelectNodes для извлечения любого из моих узлов?
Я пытаюсь проанализировать XML-документ. Этот документ является файлом AppxManifest.
Пример документа выглядит следующим образом:
<?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("//*")
возвращает каждый node, как ожидалось. В чем моя проблема?
Я также пробовал много вариантов этого запроса XPath, например
-
/Package/Applications/Application
-
Applications/Application
-
Applications/*
Как ни странно, ни один node не получает ничего. В идеале я хотел бы, чтобы узлы содержали все узлы Application
Ответы
Ответ 1
Вы должны использовать пространство имен 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);
Ответ 2
Вам нужно указать префиксы для пространств имен в NamespaceManager и XPaths. Обратите внимание, что префиксам не нужно ничего сопоставлять, кроме как между вашим 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 пространства имен "по умолчанию" (обратите внимание, что префикс по умолчанию не совпадает с пустым пространством имен) и "build". Поэтому, когда вы определяете свой менеджер пространства имен, вам нужно указать префикс для каждого из пространств имен (если вам нужно указывать узлы в обоих), но префиксы могут быть произвольными строками (действительными для префиксов, но не пустыми). То есть используйте "a" для пространства имен "default" и "bar" для пространства имен, которое отображается в "build" в XML.
Ответ 3
Вам может потребоваться прочитать это
Вот ваш код:
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']");
Ответ 4
Не в этом конкретном случае, но в общем случае, если пространство имен URN в фактическом XML не совсем совпадает с тем, которое используется для добавления пространства имен в диспетчер пространства имен (пример: отсутствует конечная косая черта), а префикс - указанный в XPath, запрос может вернуться null
.
Если пространство имен URN в XML не является надежным, синтаксис
"//*[local-name()='tag']"
будет работать.