12 Şubat 2015 Perşembe

Linq To XML 1 - XML Sorgulama

Linq ve XML
Bu yazıda linq kullanarak XML'i sorgulama örnekleri var. İkinci yazıda Linq kullanarak XML oluşturma, üçüncü yazı sorgulanan XML'i başka bir veri yapısına dönüştürme hakkında.

Linq to XML System.Linq.XML namespece'i içindeki sınıflardan oluşuyor. Şu sınıflardan oluşuyor.

XML Yükleme
XML'i yüklemek için XDocument veya XElement sınıfları kullanılabilir.İkisi arasında fark var.
Load Metodu
Load metodu string, stream, textreader, xmlreader gibi bir sürü sınıfı kullanabiliyor.

Parse Metodu
Parse metodu sadece string'i kullanabiliyor. Load varken neden Parse kullanılır bilmiyorum.

Örnek
XElement config = XElement.Parse (xml);
veya
var doc = XDocument.Parse(xml);

XDocument sınıfı
Sorgulamalarda aranılan düğüm bulunduktan sonra genellikle ya node.Value veya node.Attribute ile düğümün verisine erişilir.

Descendants metodu ile sorgulama
Descendants metodu IEnumerable döndüğü için IEnumerable ile kullanılan tüm metodları kullanabiliriz.

Tüm Düğümleri Dolaşma
Örnekte tüm düğümler dolaşılarak düğümlerin içerdikleri değerler alınıyor.
var doc = XDocument.Parse(xml);
string[] values = doc.Root.Descendants().Select(x => x.Value).ToArray();
Attribute İle Arama Yapma
Elimizde aşağıki XML olsun

<Channel Id="1">
  <Destination NameRef="MyRef"/>
<Channel>

NameRef'e göre arama yapıp Id attribute değerini almak için
XDocument doc = //...
XNamespace ns = document.Root.Name.Namespace;
var el = document.Descendants (ns + "Destination").
                              Where (x=>(string)z.Attribute ("NameRef") == "MyNameRef").First ();
string result = el.Parent.Attribute ("Id");


Namespace İçinde Arama yapma
XMLdokümanları genellikle bir namespace içindedirler. namespace url formatındadır. Aşağıda namespace ile başlayan xml görülebilir.
<?xml version="1.0" encoding="us-ascii"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
...    
</WLANProfile>
Eğer Namespace aranılan tag'e dahil edilmezse, arama default namespace içinde yapıldığı için sonuç boş döner. Bu yüzden namespace'i de aramaya dahil etmek gerekir.
XNamespace ns = document.Root.Name.Namespace;
XElement name = xdoc.Root.Element(ns + "name");

Tüm Düğümleri Dolaşma,Namespace İçinde Attribute İle Arama Yapma Örneği

Örnekte Visual Studio proje dosyasının içini okuyoruz. Projeye dahil edilen dosyanın gerçekte diskte olup olmadığını kontrol ediyoruz.

string path = "......\myproject.vcxproj";
string directoryName = Path.GetDirectoryName (path);
XDocument doc = XDocument.Load (path);
XNamespace ns = doc.Root.Name.Namespace;
var itemGroup = doc.Descendants (ns + "ItemGroup").Skip (1). First (). Elements. Select (s => s.Attribute ("Include").Value).ToList ();

foreach (var item in itemGroup)
{
  string canonicalPath = Path.Combine (directoryName, item);
  canonicalPath = new Uri (canonicalPath).LocalPath;
  if (File.Exists (canonicalPath) == false)
  {
    Console.WriteLine (canonicalPath + " does not exist!");
  }
}

DescendantsAndSelf metodu
Descendants ile aynı. Aramayı başlatan düğüm de arama kriterini sağlıyorsa sonuca dahil edilir.

Element metodu
Elimizde şöyle bir XML olsun.
<?xml version="1.0" encoding="utf-8"?>
<Server>
    JSODYAPP01T
</Server>
Server tag'inin değerini şöyle alırız
var serverName = XDocument.Load(response.GetResponseStream()).Element("Server").Value;

Elements metodu ile sorgulama
Elements ile Descendants arasındaki fark var. Descendants verilen yoldan itibaren tüm alt düğümleri dolaşır. Elements ise sadece ilk alt düğümleri dolaşırÖrnek'te XDocument türünden bir değişken olan doc'tan summary/accounts bilgileri çekiliyor.

var accounts = doc.Root.Elements("summary").Elements("account");

XInclude Nedir
XInclude ile bir xml bir başka xml belgesini içerebilir. Xinclude uzun süredir var olmasına rağmen pek kullanılmaz. Microsoft'un XML okuyucuları da xinclude tag'ini desteklemiyor. Bu yüzden aşağıda kendim bir şeyler yazdım. Verilen düğüm diğer dosya ile yer değiştiriliyor. Diğer dosyanın path ile aynı dizinde olduğunu farz ettim.

public static class XIncludeExtention
{
 // Be aware of the different 2001 and 2003 standard.
 static XNamespace IncludeNamespace = "http://www.w3.org/2003/XInclude";
    
 static  XName IncludeElementName = IncludeNamespace + "include";

 public const string IncludeLocationAttributeName = "href";
   

 public static void ReplaceXIncludes(this XDocument xDoc,string path)
 {
   ReplaceXIncludes(xDoc.Root,path);
 }
    
 static void ReplaceXIncludes(this XElement xmlElement, string path)
 {
  var r=xmlElement.Descendants(IncludeElementName).ToArray<XElement>();

  foreach (var includeElement in r)
  {
   var doc = XDocument.Load(path);
   includeElement.ReplaceWith(doc.Root);
  }
 }
}


Hiç yorum yok:

Yorum Gönder