C#でxmlファイルを読み込む

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

Package.appxmanifestファイルを、C#から読み込んで、値を取得したい。

System.Xml.Linqというのを使うのが簡単そう。

learn.microsoft.com

これを使って、やってみる。

読み込みたいPackage.appxmanifestのサンプル

こんな感じのファイルを読み込んで、「Version」の値を取りたい。

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  IgnorableNamespaces="uap rescap">

  <Identity
    Name="aff25c19-10fe-4d95-a2fb-894524b5cd03"
    Publisher="CN=xxxxx"
    Version="1.0.0.0" />   ★★←コレが取りたい!

  <Properties>
    <DisplayName>FileVerUpTool (Package)</DisplayName>
    <PublisherDisplayName>masa</PublisherDisplayName>
    <Logo>Images\StoreLogo.png</Logo>
  </Properties>

  <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
  </Dependencies>

  <Resources>
    <Resource Language="x-generate"/>
  </Resources>

  <Applications>
    <Application Id="App"
      Executable="$targetnametoken$.exe"
      EntryPoint="$targetentrypoint$">
      <uap:VisualElements
        DisplayName="FileVerUpTool (Package)"
        Description="FileVerUpTool (Package)"
        BackgroundColor="transparent"
        Square150x150Logo="Images\Square150x150Logo.png"
        Square44x44Logo="Images\Square44x44Logo.png">
        <uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" />
        <uap:SplashScreen Image="Images\SplashScreen.png" />
      </uap:VisualElements>
    </Application>
  </Applications>

  <Capabilities>
    <rescap:Capability Name="runFullTrust" />
  </Capabilities>
</Package>

実験コード

下記のようなコードで取れた。

※ついでに、「DisplayName」の値も取ってみた。

using System.Xml.Linq;

namespace ConsoleApp5
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // XMLファイルのパス
            string xmlFilePath = @"C:\git\FileVerUpTool\FileVerUpTool\FileVerUpTool (Package)\Package.appxmanifest";

            // XDocumentを使用してXMLを読み込む
            XDocument xmlDoc = XDocument.Load(xmlFilePath);

            // XMLネームスペースを定義
            XNamespace ns = "http://schemas.microsoft.com/appx/manifest/foundation/windows10";

            // Versionの値を取得
            string versionValue = xmlDoc.Root!
                                        .Element(ns + "Identity")!
                                        .Attribute("Version")!
                                        .Value;
            // DisplayNameの値を取得
            string DisplayName = xmlDoc.Root!
                                        .Element(ns + "Properties")!
                                        .Element(ns + "DisplayName")!
                                        .Value;
            // 結果を出力
            Console.WriteLine("Version: " + versionValue);
            Console.WriteLine("DisplayName: " + DisplayName);
        }
    }
}

引っかかったところ

XMLネームスペースを定義というのが必要だというのに気づかず、だいぶ詰まった。

この部分を、

            string versionValue = xmlDoc.Root!
                                        .Element(ns + "Identity")!
                                        .Attribute("Version")!
                                        .Value;

こう書いてしまっていて、

            string versionValue = xmlDoc.Root!
                                        .Element("Identity")!  // ★★←ここの「ns」を入れてなかった
                                        .Attribute("Version")!
                                        .Value;

ここが、nullになってしまっていた。

xmlDoc.Root!.Element("Identity")

Namespaceを付けると、うまく読めるようになった。

結果

Version: 1.0.0.0
DisplayName: FileVerUpTool (Package)

参考

LINQ to XML の概要

https://learn.microsoft.com/ja-jp/dotnet/standard/linq/linq-xml-overview

LINQ to XML での、名前空間の書き方
ここに引っかかった!

https://learn.microsoft.com/ja-jp/dotnet/standard/linq/create-document-namespaces-csharp