web-dev-qa-db-ja.com

XmlDocumentを使用して、名前空間の有無にかかわらずxmlファイルから読み取ります

XmlDocumentを使用して名前空間を持つxmlファイルから読み取るコードがいくつかあります。私の課題は、今読んでいるファイルの名前空間をハードコード化して、それをXmlNamespaceManagerに渡すことです。私のアプローチをもう少し柔軟性があります。任意の種類のxmlファイルから読み取るには。名前空間がある場合は、名前空間マネージャーを使用して、名前空間をハードコーディングせずに要素を読み取ります。ファイルに名前空間がない場合は、先に進んでください。それを解析します。以下は私が行ったことです。

xmldoc = new XmlDocument ();
xmldoc.Load (fileLocation);


XmlNamespaceManager nameSpaceManager = new XmlNamespaceManager(xmldoc.NameTable);

nameSpaceManager.AddNamespace ("ns","http://schemas.sample.data.org/2005");

XmlNodeList nodeList = xmldoc.SelectNodes("/ns:Demo/ns:Items",  nameSpaceManager);
if (nodeList != null) 
{
    foreach (XmlNode childNode in nodeList) 
    {
        string first = childNode.SelectSingleNode ("ns:First", nameSpaceManager).InnerText;
        string second= childNode.SelectSingleNode ("ns:Second", nameSpaceManager).InnerText;
        string third = childNode.SelectSingleNode ("ns:Third", nameSpaceManager).InnerText;
    }
}

これが私が使用しているサンプルxmlファイルです

<Demo xmlns:i="http://www.justasample.com" xmlns="http://schemas.sample.data.org/2005">
 <Items>

  <First>first</First>
  <Second>second</Second>
  <Third>third</Third>

  </Items>

</Demo>
8
naffie

次のオプションを検討できます。

  1. ドキュメントに名前空間が含まれているかどうかを判断し、それに応じてxpathクエリを作成します
  2. local-name()などの名前空間に依存しないxpathを使用します。これにより、名前空間が無視されます

オプション1

var xmlDoc = new XmlDocument();
xmlDoc.Load(fileLocation);
//determine  whether document contains namespace
var namespaceName = "ns";
var namespacePrefix = string.Empty;
XmlNamespaceManager nameSpaceManager = null;
if (xmlDoc.FirstChild.Attributes != null)
{
    var xmlns = xmlDoc.FirstChild.Attributes["xmlns"];
    if (xmlns != null)
    {
          nameSpaceManager = new XmlNamespaceManager(xmlDoc.NameTable);
          nameSpaceManager.AddNamespace(namespaceName, xmlns.Value);
          namespacePrefix = namespaceName + ":";
    }
}

XmlNodeList nodeList = xmlDoc.SelectNodes(string.Format("/{0}Demo/{0}Items",namespacePrefix), nameSpaceManager);
if (nodeList != null)
{
    foreach (XmlNode childNode in nodeList)
    {
       string first = childNode.SelectSingleNode(namespacePrefix + "First", nameSpaceManager).InnerText;
       string second = childNode.SelectSingleNode(namespacePrefix + "Second", nameSpaceManager).InnerText;
       string third = childNode.SelectSingleNode(namespacePrefix +  "Third", nameSpaceManager).InnerText;
     }
 }

オプション2

XmlNodeList nodeList = xmlDoc.SelectNodes("/*[local-name() = 'Demo']/*[local-name() = 'Items']");
if (nodeList != null)
{
    foreach (XmlNode childNode in nodeList)
    {    
        string first = childNode.SelectSingleNode("*[local-name() = 'First']").InnerText;
        string second = childNode.SelectSingleNode("*[local-name() = 'Second']").InnerText;
        string third = childNode.SelectSingleNode("*[local-name() = 'Third']").InnerText;
     }
}
13

Linq-to-XMLと私の ライブラリ拡張 、具体的には内部で処理される ToXName を使用すると、次のことができます。

XElement root = XElement.Load(fileLocation);
var items = root.Descendants("Items")
                .Select(item => new
                {
                    First = item.Get("First", ""),
                    Second= item.Get("Second", ""),
                    Third = item.Get("Third", "")
                });

したがって、すべてのFirstSecondThird要素は、Items要素の名前空間を使用して、独自の名前空間を決定します。

1
Chuck Savage