Програмиране за платформата. Net работа с xml стоян Йорданов Какво е xml?



Дата28.01.2017
Размер142.5 Kb.
Програмиране за платформата .NET
Работа с XML

Стоян Йорданов
Какво е XML?


  • XML (Extensible Markup Language) е език (или нотация) за представяне на данни. Външно прилича на HTML, тъй като и XML, и HTML наследяват SGML (Standard Generalized Markup Language), но имат и някои основни разлики.

  • SGML e стандарт за дефиниране на структурата и съдържанието на електронни документи. SGML указва по какъв начин трябва да се създават езици за описание на данни, елементите и атрибутите им и т.н.

  • XML е подмножество на езика SGML, което е оптимизирано за предаване на данни през Web. XML е начин за описание и предаване на данни, който не зависи от платформи, приложения и т.н. За разлика от HTML, където начинът на обработка на данните е широко известен (всеки браузер знае как да интерпретира HTML документ), при XML това не е така. Един XML документ съдържа просто структурирана информация, докато приложението, което ще работи с този XML документ, трябва да знае как да интерпретира тази информация.

  • XML се различава от HTML както синтактично, така и семантично.

    • Синтаксис: и двата езика използват символите <, > и &, за да описват елементи и структури. Например
      <MYELEMENT attr1=”value1” attr2=”value2”>Blah blahMYELEMENT>
      е пример за елемент с име MYELEMENT, притежаващ два атрибута (attr1 и attr2 със стойности съответно value1 и value2) и съдържание “Blah blah”.
      При HTML обаче браузерите са толерантни към некоректен език, докато при XML нещата са много по-строги. XML документите трябва да са “well-formed”, т.е. да отговарят на някакъв набор от изисквания, за да могат да бъдат считани за валидни XML документи:

      • XML документите трябва да имат само един основен (root) елемент. Всички останали елементи трябва да са вложени вътре в него.

      • Всички елементи в един XML документ трябва да имат затварящи тагове. Докато при HTML някои определени елементи нямат затварящи тагове, при XML това е недопустимо.

      • Елементите в един XML документ не бива да се припокриват. При HTML това обаче е допустимо – например Това е текст. А тук има още текст..

      • В XML, стойностите на атрибутите трябва задължително да бъдат ограждани с кавички (независимо дали ще изберем единични или двойни кавички). При HTML това може и да се пропусне, ако стойността на атрибута не съдържа интервали.

      • В текста на XML документите не могат да бъдат използвани символите <, > и &. За целта трябва да се използват съответно entity-тата &lt;, &gt; и &amp;.

    • Семантика: тук XML предлага много по-голяма свобода от HTML. Това компенсира строгия му синтаксис. При HTML езикът е един и същи (евентуално с леки изменения) и всички браузери го разбират. например навсякъде се интерпретира като начало на курсивен текст. XML обаче ни позволява сами да си дефинираме наш си собствен език за описание на данните, с наши си собствени елементи, атрибути и т.н., така че да бъде максимално удобен за описание на нашите данни. Това обаче означава, че приложението, което ще обработва XML документа, трябва да знае как да го интерпретира.

  • Това, което прави простата концепция на XML толкова привлекателна, са неговите предимства:

    • XML позволява да създаваме наш собствен език за описание на данните.

    • Обработката (parsing) на XML документи е лесна поради строгия им синтаксис. Това позволява да бъдат използвани от различни приложения, на различни платформи и т.н.

    • XML документите се базират на Unicode, което позволява по-голяма гъвкавост при описанието на данните.

    • Съдържанието на XML документите може лесно да бъде валидирано чрез използването на схема (schema). Може да се провери както структурата на документа, така и типовете данни, които съдържа.

  • Все пак трябва да се има предвид, че XML документите обикновено са по-големи като размер от съответни двоични файлове с подходяща структура, могат да отнемат повече време за обработка, повече мрежов трафик и т.н. За някои приложения обаче горните им предимства ги правят най-удачния избор.

Валидация

  • За да можем да проверим дали даден XML документ притежава определена структура и съдържа определени типове данни, можем да използваме XML Schema. Схемата представлява правила, описващи структурата и типовете данни, използвани в даден XML документ. За целта се използва XML Schema Definition Language (XSD). Чрез него в схемата могат да се посочат допустимите елементи, които могат да бъдат използвани в документа, каква трябва да бъде тяхната структура, какви атрибути могат да имат, какви данни могат да имат и т.н. Могат да се задават дори стойности по подразбиране на атрибути и елементи (в случай, че са изпуснати в XML документа).

  • Схемата е много полезна, тъй като може да служи като един вид договор за обмяна на данни между две приложения. Например ако пишем програма, която приема някакви данни във вид на XML, можем да обявим XML схемата на тези данни, така че хората, които разработват софтуер, който да подава такива данни на нашата програма, да могат да следват схемата и така те да са сигурни, че подават на нашата програма валидни данни.

  • XML схемите, базирани на XML Schema Definition Language (XSD) имат известни предимства пред по-стари технологии за валидация, като например Document Type Definition езика (DTD):

    • XML схемите са XML документи, така че те самите също са лесни за автоматична обработка и създаване.

    • XML схемите поддържат наследяване на типовете, като по този начин улесняват дефинирането на нови типове данни.

    • XML схемите предлагат и още много улеснения при дефинирането на данните, като например да групираме прости типове данни в по-сложни.

Структура

  • Един XML документ се състои от две части:

    • Пролог – това е информация преди същинските данни, която описва използвания тип кодиране (encoding), stylesheet, който да бъде използван при визуализация с web browser, използвана схема и т.н. Може да не съдържа и нищо, но може и да изглежда например ето така:
      xml version="1.0" encoding="UTF-8"?>
      mystyle.xsl"?>

    • Същински данни – това са вече същинските данни, които XML документът описва.


Работа с XML – основни класове


  • За работа с XML документи съществуват два подхода – последователно четене и обработка на документа, или създаване на дървото на XML документа в паметта и обработката му след това. За целта се използват два вида XML parser-и – т.нар. SAX Parsers (SAX – Simple API for XML), които четат документа елемент по елемент и извикват различни callback функции, в зависимост от това какъв елемент е бил прочетен, и DOM Parsers (DOM – Document Object Model), които изграждат дърво на документа. Всеки от двата подхода си има предимства и недостатъци. Предимствата на DOM са, че ни предоставя лесна обработка на данните в XML документа. Предимствата на SAX са, че за разлика от DOM, той чете данните малко по малко, и по този начин не изисква кой знае колко памет (особено при големи XML документи). SAX обаче е подходящ само за малки търсения на нещо конкретно вътре в XML документа, или за последователната му обработка, но не е удобен за по-сложни задачи.

  • В основата на обработката на XML данни в .NET Framework стои DOM (Document Object Model). Както вече споменахме, това е модел, при който чрез обекти се пресъздава структурата на XML документа в паметта, като чрез тези обекти могат да се четат данни, да се търсят, да се модифицират и т.н. Ако пък нямаме нужда от предимствата, които се предоставят от DOM, съществуват класове като XmlReader, които ни позволяват бърза и последователна обработка на документа (за това – малко по-нататък).

Document Object Model (DOM)

  • Да разгледаме следния XML документ, описващ автомобили, продавани от дадена автокъща:



    ZAZ

    20000


    Red


    Rolls Royce

    3

    Green





  • Горният XML документ би изглеждал ето така в DOM:


  • Основните обекти в този модел са т.нар. “възли” (nodes), които са представени като елипси в горната диаграма. Всеки възел има само един родител – елементът, под който се намира (в който е вложен в XML документа). Document възелът е единственият, който няма родител. Два възела, които имат един и същи родител, се наричат “siblings” (“сродни” възли).

  • В .NET Framework възлите в DOM модела представляват обекти от тип System.Xml.XmlNode. Това всъщност е абстрактен тип, от който наследяват типовете, представящи различни видове възли. Такъв е например класът XmlDocument, който предоставя и методи за манипулация на документа като цяло (зареждане / записване във файл, манипулация на различни възли в целия документ и т.н.).

  • Класът XmlNode предлага различни възможности, като например:

    • навигация из DOM дървото, например чрез свойствата

      • ParentNode – връщащо родителя на възела

      • PreviousSibling – връщащо левия съсед на възела

      • NextSibling – връщащо десния съсед на възела

      • FirstChild – връщащо първото дете на възела

      • LastChild – връщащо последното дете на възела

      • Item (индексатор в C#) – позволяващо директен достъп до някое от децата на върха

    • инспекция на текущия възел – например чрез свойствата:

      • Attributes – връщащо колекция от тип XmlAttributeCollection, съдържаща атрибутите на възела (обекти от тип XmlAttribute, също наследяващ класа XmlNode)

      • HasChildNodesдали възелът има наследници

      • IsReadOnly – дали възелът не е само за четене (т.е. да не можем да го модифицираме)

      • Name – връщащо името на възела

      • InnerXml и OuterXml – връщащи (или установяващи) съответно частта от XML документа, описваща само наследниците на възела, или пък наследниците заедно с текущия възел.

      • NodeType – връщащо стойност от изброимия тип XmlNodeType, указващ типа на текущия възел (например XmlNodeType.Attribute, Document, Element, Text, Whitespace и т.н.)

      • Value – позволяващо ни да инспектираме и модифицираме стойността на текущия възел.

      • InnerText – връщащо (или установяващо) конкатенираните стойности на възела и на всичките му деца.

    • модификация на текущия възел – например чрез методите:

      • AppendChild и PrependChild– за добавяне на ново дете съответно след или преди всички други деца на възела

      • InsertBefore и InsertAfter – за добавяне на ново дете преди или след някое конкретно от децата на възела

      • RemoveChild и ReplaceChild – съответно за премахване/подмяна на конкретно дете на възела

      • RemoveAll – за премахване на всички деца и атрибути на възела.

  • Както вече споменахме, класът XmlDocument, освен методите, наследени от XmlNode, предлага и полезни функции, като например свойството DocumentElement, чрез което можем да получим root елемента на XML документа (все пак един XML документ може да има и елементи в prolog секцията си, и без това свойство би ни било трудно да определим root елемента), свойството PreserveWhiteSpace, указващо дали при зареждане или записване на XML документа трябва да бъде запазен whitespace-ът, както и функции за създаване на различни типове елементи (като например CreateAttribute, CreateElement и други). Предлагат се и събития, чрез които можем да следим за различни промени по документа.

  • Можем да зареждаме и записваме XML документи чрез методите Load и Save на класа XmlDocument. Те могат да приемат като параметър поток, име на файл, TextReader/Writer или XmlReader/Writer.

  • Ако искаме да заредим XML документ от стринг, можем да използваме метода LoadXml на класа XmlDocument.

  • Например следната програмка зарежда горния файл, описващ автомобилите, извежда го на екрана, после извежда само данните, след което за всяка кола извежда марката, цената и валутата на екрана:
    XmlDocument doc = new XmlDocument();
    doc.Load(“MyFile.xml”);
    Console.WriteLine(doc.OuterXml);

    XmlNode rootElement = doc.DocumentElement;
    Console.WriteLine(rootElement.OuterXml);

    foreach(XmlNode node in rootElement.ChildNodes)
    {
    Console.WriteLine(“{0} {1} {2}”,
    node[“make”].InnerText,
    node[“price”].InnerText,
    node[“price”].Attributes[“currency”].InnerText);
    }


XmlDataDocument

  • Класът XmlDataDocument ни позволява да манипулираме структурирани данни както като XML, така и чрез DataSet. XmlDataDocument наследява XmlDocument, така че можем да го използваме като обикновено DOM дърво. XmlDataDocument обаче може и да бъде конструиран чрез съществуващ DataSet, или пък, както го третираме като DOM дърво, да използваме свойството му DataSet, за да получим DataSet, представящ данните в него. DataSet-ът и данните от DOM дървото остават свързани, така че ако например променим стойността на възел чрез DOM дървото, данните автоматично се отрязяват и в DataSet-а, както и обратно – промени чрез DataSet-а се отразяват в DOM дървото.

XmlReader

  • Когато нямаме нужда от предимствата, предоставяни ни от DOM, но искаме бърз начин да прочетем един XML документ, можем да използваме XmlReader-и (какво е това “reader” и “writer” може да прочетете в лекцията за потоци).

  • XmlReader е абстрактен клас, който предоставя възможности за не-кеширан, forward-only read-only достъп до някакви XML данни. При това се извършва проверка дали XML документът е well-formed, и ако не е, се генерира XmlException.

  • За разлика от SAX парсерите, където парсерът сам извиква callback функции, когато среща определени елементи, при използването на XmlReader данните трябва да бъдат изисквани изрично.

  • При XmlReader данните се четат възел по възел от XML документа чрез метода Read (включително и за да се прочете първия възел), например ето така:
    while(reader.Read())
    {

    }
    Методът Read връща true, докато има новопрочетени данни.

  • XmlReader предлага методи и свойства, чрез които може да се разбере типът на текущия елемент (свойството NodeType, връщащо стойност от тип XmlNodeType), името му (свойството Name), стойността му, ако има такава (свойствата Value и HasValue (дали има стойност)), дали има атрибути (свойствата HasAttributes и AttributeCount), за прочитане на стринговата стойност на следващия елемент (методът ReadElementString, удобен за елементи, съдържащи само текст) и т.н.

  • Класът XmlReader е абстрактен. Следните класове го наследяват:

    • XmlTextReader – за четене от поток, файл (зададен по име) или TextReader.

    • XmlNodeReader – за прочитане на вече създадени DOM дървета (в случай, че е по-удобно да бъдат обработени чрез XmlReader).

    • XmlValidatingReader – мощен валидиращ (или не-валидиращ, по желание) XML парсер, предлагащ валидация чрез DTD, XSD или XDR (XML-Data Reduced) схема. Може да се конструира както върху друг XmlReader, върху който да прилага валидация, така и просто върху поток или стринг, съдържащ XML.

    • Съществуват и други класове, наследяващи XmlReader, като например XsltReader, чрез който се връшат резултатите от XSL трансформации.

  • Например следната програмка извежда само марките на колите от горния XML документ:
    XmlTextReader reader = new XmlTextReader(“MyFile.xml”);

    while(reader.Read())
    {
    if(reader.Name == “make”)
    Console.WriteLine(reader.ReadElementString());
    }


XmlWriter

  • Можем да създаваме XML документи чрез класа XmlWriter. Това е абстрактен клас, предлагащ методи като WriteStartElement (за записване на отварящ таг), WriteAttributeString (за записване на атрибут на текущия елемент), WriteEndElement (за записване на затварящия таг на текущия елемент) и други, които ни позволяват бързо, не-кеширано, forward-only генериране на XML документи.

  • XmlWriter освен това ни позволява да контролираме и форматирането на XML документа, като например да определяме дали да бъде използвана индентация (отместване навътре – чрез свойството Indentation), какъв символ да бъде използван за отместването (свойството IndentChar), какъв символ да бъде използван за кавичка (например единична или двойна – чрез свойството QuoteChar) и т.н.

  • Тъй като XmlWriter е абстрактен клас, не можем да го използваме директно. Можем обаче да използваме наследника на XmlWriter - класът XmlTextWriter, който ни позволява записването на XML документи в поток, във файл (по зададено име) или в TextWriter обект.

  • Например, ако искаме да запишем файл, подобен на горния на екрана, можем да използваме следната програма на C#:
    XmlTextWriter writer = new XmlTextWriter(Console.Out);
    writer.Formatting = Formatting.Indented;

    writer.WriteStartElement(“cars”);
    WriteCar(writer, “ZAZ”, 20000, “USD”, “Red”);
    WriteCar(writer, “Rolls Royce”, 3, “USD”, “Green”);
    write.WriteEndElement();

  • Използваната в програмата функция WriteCar би трябвало да изглежда така:
    private static void WriteCar(
    XmlWriter
    writer,
    string
    make,
    int
    price,
    string
    currency,
    string color)
    {
    writer.WriteStartElement(“car”);

    writer.WriteStartElement(“make”);


    writer.WriteString(make);
    writer.WriteEndElement();

    writer.WriteStartElement(“price”);


    writer.WriteAttributeString(“currency”, currency);
    writer.WriteString(price.ToString());
    writer.WriteEndElement();

    writer.WriteStartElement(“color”);


    writer.WriteString(color);
    writer.WriteEndElement();

    writer.WriteEndElement();




XPath; класове за работа с XPath


  • Когато търсим някаква информация в XML документ, не сме ограничени до претърсване на DOM дървото на документа, или до прочитането му чрез XmlReader. За целта можем освен това да използваме XPath.

  • XPath (XML Path Language) е език, чрез който можем да съставяме изрази, чрез които да адресираме отделни части от даден XML документ, да задаваме критерии, на които могат да отговарят търсени от нас възли, да извличаме стрингови, числени или булеви стойности.

  • XPath се използва много от XSLT (XSL Transformations) – трансформации, базирани на XSL (XML Stylesheets). XSLT позволяват да трансформираме даден XML документ в друг, променяйки / комбинирайки информацията, съдържаща се в него. Например ако искаме от някакъв XML документ по определени правила да получим HTML, подходящ за гледане в web browser, XSLT е подходящият начин за това. За извличане на информация в XSLT се използват именно XPath изрази.

  • Ако например искаме от горния XML файл да получим всички автомобили, чиито цени са в долари, можем да го направим чрез следния XPath израз:
    /cars/car[./price/@currency=’USD’]

XPathDocument, XPathNavigator, XPathNodeIterator

  • В .NET Framework класовете за работа с XPath се намират в namespace-а System.Xml.XPath. Работата с XPath се осигурява от интерфейса IXPathNavigable. Този интерфейс се имплементира както от вече разгледания клас XmlNode (и всичките му наследници, включително XmlDocument и XmlDataDocument), така и от класа XPathDocument.

  • XPathDocument е клас, който позволява бърза, високоскоростна работа (read-only) с XPath и XSLT. Не поддържа идентичност за отделните възли (за разлика от DOM, където можем да различим всеки възел от всеки друг), но пък за сметка на това позволява много по-бърза работа с XPath и XSLT (за XSLT може да се използва класът XslTransform и по-специално методът му Transform). Позволява отваряне на XML от поток, от файл (зададен чрез URI), от TextReader или от XmlReader.

  • Основният (и единствен) метод, който се предлага от интерфейса IXPathNavigable, е методът CreateNavigator. Той връща обект от тип, наследяващ абстрактния тип XPathNavigator, който позволява придвижване по възлите на някакъв източник на данни (в случая – XML документ) чрез методи като MoveToNext, MoveToParent, MoveToFirstChild и т.н., изследване на върха чрез свойства като Name, NodeType и други (подобни на тези от класа XmlNode), както и изпълнение на XPath заявки върху него.

  • Достъпът до данни чрез XPathNavigator е read-only. Резултатите от XPath заявките се връщат във вид на XPathNodeIterator обект, чрез който метод MoveNext можем да се придвижваме по възлите, отговарящи на заявката. За всеки от тях можем да използваме свойството Current на XPathNodeIterator обекта, за да получим XPathNavigator, позициониран върху текущия възел, и да го изследваме чрез съответните свойства на XPathNavigator обекта.

  • Ако искаме да модифицираме възли, до които сме достигнали чрез XPathNavigator, за целта трябва първо да получим указател към самия възел (XmlNode обект), след което да го модифицираме. За целта можем да използваме метода IHasXmlNode.GetNode, в случай, че съответният XPathNavigator поддържа този интерфейс (т.е. ако сме го получили от обект, който има възли, като например XmlDocument). Например следното парче код получава възелът, върху който е позициониран XmlNavigator-ът navigator:
    XmlNode node = ((IHasXmlNode)navigator).GetNode();

  • Ако например искаме от горния XML да извлечем цените на всички ЗАЗ-ове, можем да го направим със следната програма:
    XPathDocument doc = new XPathDocument(“MyFile.xml”);
    XPathNavigator navigator = doc.CreateNavigator();

    XPathNodeIterator iterator = navigator.Select(“/*/car[make=’ZAZ’]/price”);

    while(iterator.MoveNext())
    {
    Console.WriteLine(iterator.Current.Value);
    }


  • Забележете, че върнатият XPathNodeIterator веднага след заявката сочи към оригиналния връх, в който тя е изпълненя, и трябва да се извика MoveNext, за да бъде позициониран върху първият резултат от заявката.


База данных защищена авторским правом ©obuch.info 2016
отнасят до администрацията

    Начална страница