Чтение XML
Перебор элементов XML-документа
Для чтения XML-документа предназначен экземпляр типа ЧтениеXml
. В общем случае читать XML-документ можно из экземпляра типа, производного от ПотокЧтения
. Мы будем рассматривать чтение документа из файла. В качестве примера файла рассмотрим фрагмент манифеста универсального приложения ОС Windows. Это достаточно сложный XML-документ, который позволит увидеть основные особенности чтения таких документов.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Package IgnorableNamespaces="uap mp build"
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build">
<mp:PhoneIdentity
PhoneProductId="A588A326-FD4F-441C-83B2-AA0B8554C548"
PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>ms-resource:AppName</DisplayName>
<PublisherDisplayName>1C LLC</PublisherDisplayName>
<Logo>icon_50x50.png</Logo>
</Properties>
<Resources>
<Resource Language="EN-US"/>
</Resources>
<Capabilities>
<uap:Capability Name="appointments"/>
<uap:Capability Name="contacts"/>
<Capability Name="internetClient"/>
<Capability Name="privateNetworkClientServer"/>
<Capability Name="internetClientServer"/>
<uap:Capability Name="musicLibrary"/>
<uap:Capability Name="picturesLibrary"/>
<uap:Capability Name="removableStorage"/>
<uap:Capability Name="videosLibrary"/>
<DeviceCapability Name="location"/>
<DeviceCapability Name="webcam"/>
<DeviceCapability Name="microphone"/>
<DeviceCapability Name="proximity"/>
</Capabilities>
<build:Metadata>
<build:Item Name="cl.exe" Version="19.16.27030.1 built by: vcwrkspc"/>
<build:Item Name="VisualStudio" Version="15.0"/>
<build:Item Name="OperatingSystem" Version="6.3.9600.16384 (winblue_rtm.130821-1623)"/>
<build:Item Name="Microsoft.Build.AppxPackage.dll" Version="15.0.28307.104"/>
<build:Item Name="ProjectGUID" Value="{15630E4C-5D90-44AB-9CF0-FBC27700DDAA}"/>
<build:Item Name="OptimizingToolset" Value="None"/>
<build:Item Name="TargetRuntime" Value="Native"/>
<build:Item Name="Microsoft.Windows.UI.Xaml.Build.Tasks.dll" Version="15.0.28307.102"/>
<build:Item Name="WindowsMobile" Version="10.0.17763.0"/>
<build:Item Name="MakePri.exe" Version="10.0.17763.132 (WinBuild.160101.0800)"/>
</build:Metadata>
</Package>
Рассматриваемый экземпляр читает XML-документ строго последовательно. Каждый элемент имеет свое имя, которое отображается в свойство Имя
экземпляра ЧтениеXml
. Простейший пример такого чтения будет выглядеть примерно следующим образом:
метод метод ЧтениеXml(): Массив<Строка>
пер ВременныйКаталог = СредаИсполнения.ПолучитьПеременную("temp")
пер Файл = новый Файл(ВременныйКаталог + "\\manifest.xml")
пер СодержимоеXML: Массив<Строка>
пер Чтение = новый ЧтениеXml(Файл.ОткрытьПотокЧтения())
пока Чтение.Следующий()
// Читаем имя текущего узла
СодержимоеXML.Добавить("Имя узла - " + Чтение.Имя)
;
возврат СодержимоеXML
;
Вызов метода Следующий()
приводит к последовательному обходу всех элементов читаемого XML-документа. Когда данный метод вернет значение Ложь
, это будет означать, что файл завершился. Результат исполнения этого программного кода, записанный в массив строк СодержимоеXML
, будет не очень понятным (приведен фрагмент):
Имя узла - Package
Имя узла - mp:PhoneIdentity
Имя узла - mp:PhoneIdentity
Имя узла - Properties
Имя узла - DisplayName
Имя узла -
Имя узла - DisplayName
Имя узла - PublisherDisplayName
Имя узла -
Имя узла - PublisherDisplayName
Имя узла - Logo
Имя узла -
Имя узла - Logo
Имя узла - Properties
...
Первое, что смущает при взгляде на результат работы программы, — некоторые элементы выводятся один раз, некоторые — два раза, а некоторые элементы вообще не имеют имени. Попробуем разобраться с этим вопросом.
Каждый элемент XML имеет открывающий и закрывающий тег. При этом оба этих тега в теле документа имеют одинаковое имя: <tag>
текст</tag>
. Закрывающий тег несколько отличается, но это нам сейчас не интересно. Экземпляр ЧтениеXml
читает наш документ последовательно. При чтении отдельно читается начало элемента и отдельно — его окончание. А так как имена в открывающем и закрывающем тегах одинаковые, мы видим две строки с одним именем. Соответственно, если строка с именем только одна, то скорее всего, до закрывающего тега еще не дошли.
Чтобы определить, какой элемент в данный момент считан из нашего документа, тип ЧтениеXml
предоставляет свойство ВидУзла
. С помощью этого свойства мы можем проверить наше предыдущее утверждение. Перепишем строку СодержимоеXML.Добавить("Имя узла - " + Чтение.Имя)
из примера:
СодержимоеXML.Добавить("Имя узла - " + Чтение.Имя + ", тип - " + Чтение.ВидУзла)
В результате работы нашего примера в массиве СодержимоеXML
будут следующие элементы (приведен фрагмент того же размера):
Имя узла - Package, тип - StartElement
Имя узла - mp:PhoneIdentity, тип - StartElement
Имя узла - mp:PhoneIdentity, тип - EndElement
Имя узла - Properties, тип - StartElement
Имя узла - DisplayName, тип - StartElement
Имя узла - , тип - Text
Имя узла - DisplayName, тип - EndElement
Имя узла - PublisherDisplayName, тип - StartElement
Имя узла - , тип - Text
Имя узла - PublisherDisplayName, тип - EndElement
Имя узла - Logo, тип - StartElement
Имя узла - , тип - Text
Имя узла - Logo, тип - EndElement
Имя узла - Properties, тип - EndElement
...
Мы видим, что тип элемента (или узла XML-документа) в каждой строке вывода изменяется. В текущем примере мы видим три разных значения:
StartElement
— таким образом описывается начало элемента.EndElement
— таким образом описывается окончание элемента.Text
— таким типом отмечается содержимое узла XML-документа, если это содержимое не является другим элементом.
Наши утверждения, высказанные ранее, подтвердились практически. Также получили объяснения элементы, которые не имеют имени. В XML-документе узлы, которые имеют содержимое, выглядят следующим образом:
`<tag>`содержимое`</tag>`
В то же время не все узлы такое содержимое имеют. Для того чтобы определить, имеет узел содержимое или нет, предназначено свойство ЧтениеXml.ИмеетЗначение
.
Наш пример, модифицированный для того, чтобы выводить содержимое для элементов, которые его содержат, выглядит следующим образом:
метод ЧтениеXml(): Массив<Строка>
пер ВременныйКаталог = СредаИсполнения.ПолучитьПеременную("temp")
пер Файл = новый Файл(ВременныйКаталог + "\\manifest.xml")
пер СодержимоеXML: Массив<Строка>
пер Чтение = новый ЧтениеXml(Файл.ОткрытьПотокЧтения())
пока Чтение.Следующий()
// Читаем имя текущего узла
СодержимоеXML.Добавить("Имя узла - " + Чтение.Имя + ", тип - " + Чтение.ВидУзла)
если Чтение.ИмеетЗначение
СодержимоеXML.Добавить("Содержимое: " + Чтение.Значение)
;
;
возврат СодержимоеXML
;
Массив СодержимоеXML
будет содержать следующие элементы:
Имя узла - Package, тип - StartElement
Имя узла - mp:PhoneIdentity, тип - StartElement
Имя узла - mp:PhoneIdentity, тип - EndElement
Имя узла - Properties, тип - StartElement
Имя узла - DisplayName, тип - StartElement
Имя узла - , тип - Text
Содержимое: ms-resource:AppName
Имя узла - DisplayName, тип - EndElement
Имя узла - PublisherDisplayName, тип - StartElement
Имя узла - , тип - Text
Содержимое: 1C LLC
Имя узла - PublisherDisplayName, тип - EndElement
Имя узла - Logo, тип - StartElement
Имя узла - , тип - Text
Содержимое: icon_50x50.png
Имя узла - Logo, тип - EndElement
Имя узла - Properties, тип - EndElement
...
Кроме безусловного чтения следующего элемента, с помощью экземпляра ЧтениеXml
можно читать элементы какого-то заранее известного имени. Чтение будет выполняться без учета иерархии элементов. Для того, чтобы выполнить такое чтение, необходимо использовать метод СледующийДо()
. Параметром метода является имя элемента, начало которого необходимо прочитать. После того как выполнено позиционирование на требуемый элемент, необходимо вызвать метод Следующий()
, а затем снова вызвать метод СледующийДо()
. Пример демонстрирует чтение элементов с именем Capability
. Всего их три.
метод ЧтениеXmlОпределенногоЭлемента(): Массив<Строка>
пер ВременныйКаталог = СредаИсполнения.ПолучитьПеременную("temp")
пер Файл = новый Файл(ВременныйКаталог + "\\manifest.xml")
пер СодержимоеXML: Массив<Строка>
пер Чтение = новый ЧтениеXml(Файл.ОткрытьПотокЧтения())
пока Чтение.СледующийДо("Capability")
СодержимоеXML.Добавить("Имя узла - " + Чтение.Имя + ", тип - " + Чтение.ВидУзла)
если Чтение.ИмеетЗначение
СодержимоеXML.Добавить("Содержимое: " + Чтение.Значение)
;
Чтение.Следующий()
;
возврат СодержимоеXML
;