yotiky Tech Blog

とあるエンジニアの備忘録

C# - XmlReader の使い方

learn.microsoft.com

適用対象は、.NET Framework 1.1 以降。

目次

検証環境

  • LINQPad 7
  • .NET 7.0

XmlReader の使い方

基本的な要素の取り扱い。

private void WriteConsole(XmlReader xr)
{
    if (xr.NodeType == XmlNodeType.Whitespace)
        return;

    Console.WriteLine($"NodeType = {xr.NodeType}, Name = {xr.Name}, Value = {xr.Value}");

    if (xr.NodeType == XmlNodeType.Element)
    {
        if (xr.HasAttributes)
        {
            var separator = "";
            Console.Write("Attribute : ");
            while (xr.MoveToNextAttribute())
            {
                Console.Write($"{separator}{xr.Name} = {xr.Value}");
                separator = ", ";
            }
            Console.WriteLine();
        }
    }
}

サンプルのPurchaseOrder.xmlは以下の通り。

<?xml version="1.0"?>
<PurchaseOrder PurchaseOrderNumber="99503" OrderDate="1999-10-20">
    <Address Type="Shipping">
        <Name>Ellen Adams</Name>
        <Street>123 Maple Street</Street>
        <City>Mill Valley</City>
        <State>CA</State>
        <Zip>10999</Zip>
        <Country>USA</Country>
    </Address>
    <Address Type="Billing">
        <Name>Tai Yee</Name>
        <Street>8 Oak Avenue</Street>
        <City>Old Town</City>
        <State>PA</State>
        <Zip>95819</Zip>
        <Country>USA</Country>
    </Address>
    <DeliveryNotes>Please leave packages in shed by driveway.</DeliveryNotes>
    <Items>
        <Item PartNumber="872-AA">
            <ProductName>Lawnmower</ProductName>
            <Quantity>1</Quantity>
            <USPrice>148.95</USPrice>
            <Comment>Confirm this is electric</Comment>
        </Item>
        <Item PartNumber="926-AA">
            <ProductName>Baby Monitor</ProductName>
            <Quantity>2</Quantity>
            <USPrice>39.98</USPrice>
            <ShipDate>1999-05-21</ShipDate>
        </Item>
    </Items>
</PurchaseOrder>

実行結果の抜粋。

NodeType = XmlDeclaration, Name = xml, Value = version="1.0"
NodeType = Element, Name = PurchaseOrder, Value = 
Attribute : PurchaseOrderNumber = 99503, OrderDate = 1999-10-20
NodeType = Element, Name = Address, Value = 
Attribute : Type = Shipping
NodeType = Element, Name = Name, Value = 
NodeType = Text, Name = , Value = Ellen Adams
NodeType = EndElement, Name = Name, Value = 
NodeType = Element, Name = Street, Value = 
NodeType = Text, Name = , Value = 123 Maple Street
NodeType = EndElement, Name = Street, Value = 
NodeType = Element, Name = City, Value = 
NodeType = Text, Name = , Value = Mill Valley
NodeType = EndElement, Name = City, Value = 
NodeType = Element, Name = State, Value = 
NodeType = Text, Name = , Value = CA
NodeType = EndElement, Name = State, Value = 
NodeType = Element, Name = Zip, Value = 
NodeType = Text, Name = , Value = 10999
NodeType = EndElement, Name = Zip, Value = 
NodeType = Element, Name = Country, Value = 
NodeType = Text, Name = , Value = USA
NodeType = EndElement, Name = Country, Value = 
NodeType = EndElement, Name = Address, Value = 
NodeType = Element, Name = Address, Value = 
Attribute : Type = Billing
(省略)
NodeType = EndElement, Name = Address, Value = 
NodeType = Element, Name = DeliveryNotes, Value = 
NodeType = Text, Name = , Value = Please leave packages in shed by driveway.
NodeType = EndElement, Name = DeliveryNotes, Value = 
(省略)
  • 上から逐次読み込む
  • XML宣言は、XmlDeclaration
  • タグは、ElementとEndElement、同じNameで囲まれる、Valueは空
  • タグで囲まれた文字は、Text、Valueに値、Nameは空
  • 属性は MoveToNextAttribute で読める、NameとValueのペア
  • 入れ子の階層は、対のElementとEndElementの間に挟み込む

ファイルから読み込む

    var path = @"C:\Workspace\LINQPad Queries\XML\PurchaseOrder.xml";

    using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
    using (var xr = XmlReader.Create(fs))
    {
        while (xr.Read())
        {
            WriteConsole(xr);
        }
    };

文字列から読み込む

XmlReaderSettingsAsync を true して設定することで非同期で呼び出せる。

    var xml = 
@"<PurchaseOrder PurchaseOrderNumber=""99503"" OrderDate=""1999-10-20"">
  <Address Type=""Shipping"">
      <Name>Ellen Adams</Name>
      <Street>123 Maple Street</Street>
      <City>Mill Valley</City>
      <State>CA</State>
      <Zip>10999</Zip>
      <Country>USA</Country>
  </Address>
</PurchaseOrder>";

    var settings = new XmlReaderSettings
    {
        Async = true,
    };

    using (var sr = new StringReader(xml))
    using (var xr = XmlReader.Create(sr, settings))
    {
        while (await xr.ReadAsync())
        {
            WriteConsole(xr);
        }
    };

実行結果。

NodeType = Element, Name = PurchaseOrder, Value = 
Attribute : PurchaseOrderNumber = 99503, OrderDate = 1999-10-20
NodeType = Element, Name = Address, Value = 
Attribute : Type = Shipping
NodeType = Element, Name = Name, Value = 
NodeType = Text, Name = , Value = Ellen Adams
NodeType = EndElement, Name = Name, Value = 
NodeType = Element, Name = Street, Value = 
NodeType = Text, Name = , Value = 123 Maple Street
NodeType = EndElement, Name = Street, Value = 
NodeType = Element, Name = City, Value = 
NodeType = Text, Name = , Value = Mill Valley
NodeType = EndElement, Name = City, Value = 
NodeType = Element, Name = State, Value = 
NodeType = Text, Name = , Value = CA
NodeType = EndElement, Name = State, Value = 
NodeType = Element, Name = Zip, Value = 
NodeType = Text, Name = , Value = 10999
NodeType = EndElement, Name = Zip, Value = 
NodeType = Element, Name = Country, Value = 
NodeType = Text, Name = , Value = USA
NodeType = EndElement, Name = Country, Value = 
NodeType = EndElement, Name = Address, Value = 
NodeType = EndElement, Name = PurchaseOrder, Value =