I'm trying to parse an XML document. The document in question is an AppxManifest file.
An example document looks like this:
<?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>
I try to parse it like so:
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");
However, after I execute this, nodes
will never contain anything. The xml document is loaded and such though. using SelectNodes("//*")
returns every node as expected. What is my problem here?
I've also tried many variations on that XPath query such as
/Package/Applications/Application
Applications/Application
Applications/*
Nothing appears to retrieve the single node though. Ideally, I'd like for nodes to contain all of the Application
nodes
XDocument is from the LINQ to XML API, and XmlDocument is the standard DOM-style API for XML. If you know DOM well, and don't want to learn LINQ to XML, go with XmlDocument . If you're new to both, check out this page that compares the two, and pick which one you like the looks of better.
XmlNodeList supports iteration and indexed access. XmlNodeList is returned by the following properties and methods. XmlNode. ChildNodes - Returns an XmlNodeList containing all the children of the node. XmlNode.
You have to use xml namespace specifically to select them. consider
"//*[local-name()='Applications']/*[local-name()='Application']"
in your case this code may also work well:
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);
You need to specify prefixes for namespaces in NamespaceManager and XPaths. Note that prefixes does not need to match anything except between your XPath and your namespace manager*.
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);
And as pointed out by other answers XPath that accepts any namespace is another option.
*) I.e. in your particular sample there are 2 namespaces "default" (note that default prefix is not the same as empty namespace) and "build". So when you define your namespace manager you need to specify a prefix for each of the namespace (if you need to target nodes in both), but prefixes can be arbitrary strings (valid for prefixes but not empty). I.e. use "a" for "default" namespace and "bar" for namespace that mapped to "build" in the XML.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With