19

我正在尝试解析 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 文档已加载等。usingSelectNodes("//*")按预期返回每个节点。我的问题是什么?

我还尝试了该 XPath 查询的许多变体,例如

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

不过,似乎没有任何东西可以检索单个节点。理想情况下,我希望节点包含所有Application节点

4

4 回答 4

45

您必须专门使用 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);
于 2012-09-26T18:16:41.507 回答
11

您需要在 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 是另一种选择。

*) 即在您的特定示例中有 2 个命名空间“默认”(请注意,默认前缀与空命名空间不同)和“构建”。因此,当您定义命名空间管理器时,您需要为每个命名空间指定一个前缀(如果您需要在两者中定位节点),但前缀可以是任意字符串(对前缀有效但不能为空)。即,使用“a”作为“默认”命名空间,使用“bar”作为映射到 XML 中“build”的命名空间。

于 2012-09-26T18:31:40.173 回答
5

不是在这种特殊情况下,但一般情况下,如果实际 XML 中的命名空间 URN 与用于将命名空间添加到命名空间管理器的名称不完全相同(例如:缺少尾部斜杠),并且在 XPath 中指定了前缀,查询可能会返回null

如果 XML 中的命名空间 URN 不可靠,则语法

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

将工作。

于 2016-11-11T18:38:35.637 回答
4

你可能需要阅读这个

这是你的代码:

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']");
于 2012-09-26T18:29:44.713 回答