XStreamingElement Класс
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Представляет элементы в xml-дереве, поддерживающем отложенные выходные данные потоковой передачи.
public ref class XStreamingElement
public class XStreamingElement
type XStreamingElement = class
Public Class XStreamingElement
- Наследование
-
XStreamingElement
Примеры
В следующем примере сначала создается исходное xml-дерево. Затем он создает преобразование исходного XML-дерева с помощью XElement. Это преобразование создает новое дерево в памяти. Затем он создает преобразование исходного XML-дерева с помощью XStreamingElement. Это преобразование не выполняет запрос, пока преобразованное дерево не сериализуется в консоль. Его использование памяти меньше.
XElement srcTree = new XElement("Root",
new XElement("Child", 1),
new XElement("Child", 2),
new XElement("Child", 3),
new XElement("Child", 4),
new XElement("Child", 5)
);
XElement dstTree1 = new XElement("NewRoot",
from el in srcTree.Elements()
where (int)el >= 3
select new XElement("DifferentChild", (int)el)
);
XStreamingElement dstTree2 = new XStreamingElement("NewRoot",
from el in srcTree.Elements()
where (int)el >= 3
select new XElement("DifferentChild", (int)el)
);
Console.WriteLine(dstTree1);
Console.WriteLine("------");
Console.WriteLine(dstTree2);
Dim srcTree As XElement = _
<Root>
<Child>1</Child>
<Child>2</Child>
<Child>3</Child>
<Child>4</Child>
<Child>5</Child>
</Root>
Dim dstTree1 As XElement = _
<NewRoot>
<%= From el In srcTree.Elements _
Where (el.Value >= 3) _
Select <DifferentChild><%= el.Value %></DifferentChild> %>
</NewRoot>
Dim dstTree2 As XStreamingElement = New XStreamingElement("NewRoot", _
From el In srcTree.Elements _
Where el.Value >= 3 _
Select <DifferentChild><%= el.Value %></DifferentChild> _
)
Console.WriteLine(dstTree1)
Console.WriteLine("------")
Console.WriteLine(dstTree2)
В примере получается следующий вывод.
<NewRoot>
<DifferentChild>3</DifferentChild>
<DifferentChild>4</DifferentChild>
<DifferentChild>5</DifferentChild>
</NewRoot>
------
<NewRoot>
<DifferentChild>3</DifferentChild>
<DifferentChild>4</DifferentChild>
<DifferentChild>5</DifferentChild>
</NewRoot>
Одним из способов обработки текстового файла является запись метода расширения, который передает текстовый файл строке в одно время с помощью yield return конструкции. Затем можно написать запрос LINQ, который обрабатывает текстовый файл в отложенном режиме. При использовании XStreamingElement выходных данных для потоковой передачи можно создать преобразование из текстового файла в XML, который использует минимальный объем памяти независимо от размера исходного текстового файла.
Следующий текстовый файл, People.txt, является источником для этого примера.
#This is a comment
1,Tai,Yee,Writer
2,Nikolay,Grachev,Programmer
3,David,Wright,Inventor
Следующий код содержит метод расширения, который передает строки текстового файла в отложенном режиме.
public static class StreamReaderSequence
{
public static IEnumerable<string> Lines(this StreamReader source)
{
String line;
if (source == null)
throw new ArgumentNullException("source");
while ((line = source.ReadLine()) != null)
{
yield return line;
}
}
}
class Program
{
static void Main(string[] args)
{
StreamReader sr = new StreamReader("People.txt");
XStreamingElement xmlTree = new XStreamingElement("Root",
from line in sr.Lines()
let items = line.Split(',')
where !line.StartsWith("#")
select new XElement("Person",
new XAttribute("ID", items[0]),
new XElement("First", items[1]),
new XElement("Last", items[2]),
new XElement("Occupation", items[3])
)
);
Console.WriteLine(xmlTree);
sr.Close();
}
}
Module StreamReaderSequence
<Runtime.CompilerServices.Extension>
Public Iterator Function Lines(source As IO.StreamReader) As IEnumerable(Of String)
If source Is Nothing Then Throw New ArgumentNullException("source")
Dim line As String = source.ReadLine()
While (line <> Nothing)
Yield line
line = source.ReadLine()
End While
End Function
End Module
Module Module1
Sub Main()
Dim sr As New IO.StreamReader("People.txt")
Dim xmlTree As New XStreamingElement("Root",
From line In sr.Lines()
Let items = line.Split(","c)
Where Not line.StartsWith("#")
Select <Person ID=<%= items(0) %>>
<First><%= items(1) %></First>
<Last><%= items(2) %></Last>
<Occupation><%= items(3) %></Occupation>
</Person>)
Console.WriteLine(xmlTree)
sr.Close()
End Sub
End Module
В примере получается следующий вывод.
<Root>
<Person ID="1">
<First>Tai</First>
<Last>Yee</Last>
<Occupation>Writer</Occupation>
</Person>
<Person ID="2">
<First>Nikolay</First>
<Last>Grachev</Last>
<Occupation>Programmer</Occupation>
</Person>
<Person ID="3">
<First>David</First>
<Last>Wright</Last>
<Occupation>Inventor</Occupation>
</Person>
</Root>
Иногда необходимо преобразовать большие XML-файлы и записать приложение таким образом, чтобы объем памяти приложения был предсказуемым. Если вы пытаетесь заполнить xml-дерево очень большим XML-файлом, использование памяти будет пропорциональным размеру файла (то есть чрезмерному). Поэтому вместо этого следует использовать метод потоковой передачи.
Некоторые стандартные операторы запросов, такие как OrderByитерацию источника, собирают все данные, сортируют его, а затем, наконец, дают первый элемент в последовательности. Обратите внимание, что если вы используете оператор запроса, который материализует источник перед получением первого элемента, вы не будете хранить небольшой объем памяти для приложения.
Даже если вы используете метод, описанный в описании, при попытке собрать xml-дерево, содержащее преобразованный документ, использование памяти может быть слишком большим.
В следующем примере показано, как передавать фрагменты XML с доступом к сведениям заголовка.
В этом примере используются отложенные возможности выполнения для потоковой передачи выходных XStreamingElement данных.
Обратите внимание, что пользовательская ось (StreamCustomerItem) специально написана таким образом, чтобы он ожидал документ с Customerэлементами Nameи Item элементами, и что эти элементы будут упорядочены, как показано в следующем документе Source.xml. Однако более надежная реализация будет проверять исходный документ с помощью XSD или будет готова проанализировать недопустимый документ.
Ниже приведен исходный документ Source.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Root>
<Customer>
<Name>A. Datum Corporation</Name>
<Item>
<Key>0001</Key>
</Item>
<Item>
<Key>0002</Key>
</Item>
<Item>
<Key>0003</Key>
</Item>
<Item>
<Key>0004</Key>
</Item>
</Customer>
<Customer>
<Name>Fabrikam, Inc.</Name>
<Item>
<Key>0005</Key>
</Item>
<Item>
<Key>0006</Key>
</Item>
<Item>
<Key>0007</Key>
</Item>
<Item>
<Key>0008</Key>
</Item>
</Customer>
<Customer>
<Name>Southridge Video</Name>
<Item>
<Key>0009</Key>
</Item>
<Item>
<Key>0010</Key>
</Item>
</Customer>
</Root>
Следующий код содержит метод, который использует для потоковой XmlReader передачи исходного XML-кода. Он используется XStreamingElement для потоковой передачи нового XML-кода.
static IEnumerable<XElement> StreamCustomerItem(string uri)
{
using (XmlReader reader = XmlReader.Create(uri))
{
XElement name = null;
XElement item = null;
reader.MoveToContent();
// Parse the file, save header information when encountered, and yield the
// Item XElement objects as they are created.
// loop through Customer elements
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element
&& reader.Name == "Customer")
{
// move to Name element
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element &&
reader.Name == "Name")
{
name = XElement.ReadFrom(reader) as XElement;
break;
}
}
// loop through Item elements
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.EndElement)
break;
if (reader.NodeType == XmlNodeType.Element
&& reader.Name == "Item")
{
item = XElement.ReadFrom(reader) as XElement;
if (item != null)
{
XElement tempRoot = new XElement("Root",
new XElement(name)
);
tempRoot.Add(item);
yield return item;
}
}
}
}
}
}
}
static void Main(string[] args)
{
XStreamingElement root = new XStreamingElement("Root",
from el in StreamCustomerItem("Source.xml")
select new XElement("Item",
new XElement("Customer", (string)el.Parent.Element("Name")),
new XElement(el.Element("Key"))
)
);
root.Save("Test.xml");
Console.WriteLine(File.ReadAllText("Test.xml"));
}
Iterator Function StreamCustomerItem(uri As String) As IEnumerable(Of XElement)
Dim name As XElement = Nothing
Dim item As XElement = Nothing
Dim reader As XmlReader = XmlReader.Create(uri)
reader.MoveToContent()
' Parse the file, save header information when encountered, and yield the
' Item XElement objects as they are created.
' Loop through Customer elements.
While (reader.Read())
If (reader.NodeType = XmlNodeType.Element And reader.Name = "Customer") Then
While (reader.Read())
' Move to Name element
If (reader.NodeType = XmlNodeType.Element And reader.Name = "Name") Then
name = CType(XElement.ReadFrom(reader), XElement)
Exit While
End If
End While
' Loop through Item elements
While (reader.Read())
If (reader.NodeType = XmlNodeType.EndElement) Then
Exit While
End If
If (reader.NodeType = XmlNodeType.Element And reader.Name = "Item") Then
item = CType(XElement.ReadFrom(reader), XElement)
If (Not (item Is Nothing)) Then
Dim tempRoot = New XElement("Root",
New XElement(name)
)
tempRoot.Add(item)
Yield item
End If
End If
End While
End If
End While
reader.Close()
End Function
Sub Main()
Dim root As New XStreamingElement("Root",
From el In StreamCustomerItem("c:\trash\Source.xml")
Select New XElement("Item",
New XElement("Customer", CStr(el.Parent.Element("Name"))),
New XElement(el.Element("Key"))))
root.Save("c:\trash\Test.xml")
Console.WriteLine(System.IO.File.ReadAllText("c:\trash\Test.xml"))
End Sub
В примере получается следующий вывод.
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Item>
<Customer>A. Datum Corporation</Customer>
<Key>0001</Key>
</Item>
<Item>
<Customer>A. Datum Corporation</Customer>
<Key>0002</Key>
</Item>
<Item>
<Customer>A. Datum Corporation</Customer>
<Key>0003</Key>
</Item>
<Item>
<Customer>A. Datum Corporation</Customer>
<Key>0004</Key>
</Item>
<Item>
<Customer>Fabrikam, Inc.</Customer>
<Key>0005</Key>
</Item>
<Item>
<Customer>Fabrikam, Inc.</Customer>
<Key>0006</Key>
</Item>
<Item>
<Customer>Fabrikam, Inc.</Customer>
<Key>0007</Key>
</Item>
<Item>
<Customer>Fabrikam, Inc.</Customer>
<Key>0008</Key>
</Item>
<Item>
<Customer>Southridge Video</Customer>
<Key>0009</Key>
</Item>
<Item>
<Customer>Southridge Video</Customer>
<Key>0010</Key>
</Item>
</Root>
Комментарии
Этот класс позволяет создать XML-дерево, которое поддерживает отложенные выходные данные потоковой передачи. Этот класс используется для создания дерева XML в очень похожем виде на создание XML-дерева с помощью XElement. Тем не менее, существует фундаментальное различие. При использовании запроса LINQ для указания содержимого при создании xml-дерева с помощью XElementпеременной запроса выполняется итерация во время построения XML-дерева, а результаты запроса добавляются в xml-дерево. Напротив, при создании XML-дерева с помощью XStreamingElementссылки на переменную запроса сохраняется в xml-дереве без итерации. Запросы итерируются только при сериализации. Это позволяет создавать большие XML-деревья при сохранении меньшего объема памяти.
Если вы выполняете потоковую передачу из входного источника, например текстовый файл, вы можете прочитать очень большой текстовый файл и создать очень большой XML-документ при сохранении небольшого объема памяти.
Другой сценарий заключается в том, что у вас есть большое дерево XML, загруженное в память, и вы хотите создать преобразованную версию документа. Если вы создаете новый документ с помощью XElement, то после завершения преобразования у вас будет два больших дерева XML в памяти. Однако если вы создаете новое XML-дерево с помощью XStreamingElement, рабочий набор будет эффективно вырезаться в половину.
Обратите внимание, что при отладке программы, которая использует XStreamingElementзначение объекта, вызывается его ToString метод. Это приводит к сериализации XML. Если семантика запроса элемента потоковой передачи такова, что элемент потоковой передачи может передаваться только один раз, это может привести к нежелательному поведению при отладке.
Конструкторы
| Имя | Описание |
|---|---|
| XStreamingElement(XName, Object) |
Инициализирует новый экземпляр XStreamingElement класса с указанным именем и содержимым. |
| XStreamingElement(XName, Object[]) |
Инициализирует новый экземпляр XStreamingElement класса с указанным именем и содержимым. |
| XStreamingElement(XName) |
Инициализирует новый экземпляр XElement класса из указанного XName. |
Свойства
| Имя | Описание |
|---|---|
| Name |
Возвращает или задает имя этого элемента потоковой передачи. |
Методы
| Имя | Описание |
|---|---|
| Add(Object) |
Добавляет указанное содержимое в качестве дочерних XStreamingElementэлементов. |
| Add(Object[]) |
Добавляет указанное содержимое в качестве дочерних XStreamingElementэлементов. |
| Equals(Object) |
Определяет, равен ли указанный объект текущему объекту. (Унаследовано от Object) |
| GetHashCode() |
Служит хэш-функцией по умолчанию. (Унаследовано от Object) |
| GetType() |
Возвращает Type текущего экземпляра. (Унаследовано от Object) |
| MemberwiseClone() |
Создает неглубокую копию текущей Object. (Унаследовано от Object) |
| Save(Stream, SaveOptions) |
Выводит это XStreamingElement в указанный Streamпараметр, при необходимости указывая поведение форматирования. |
| Save(Stream) |
Выводит это XStreamingElement в указанный Streamобъект. |
| Save(String, SaveOptions) |
Сериализуйте этот элемент потоковой передачи в файл, при необходимости отключая форматирование. |
| Save(String) |
Сериализируйте этот элемент потоковой передачи в файл. |
| Save(TextWriter, SaveOptions) |
Сериализуйте этот элемент потоковой передачи в TextWriterрежиме автоматического отключения форматирования. |
| Save(TextWriter) |
Сериализуйте этот элемент потоковой передачи в объект TextWriter. |
| Save(XmlWriter) |
Сериализуйте этот элемент потоковой передачи в объект XmlWriter. |
| ToString() |
Возвращает форматированный (отступ) XML для этого элемента потоковой передачи. |
| ToString(SaveOptions) |
Возвращает XML-код для этого элемента потоковой передачи, при необходимости отключая форматирование. |
| WriteTo(XmlWriter) |
Записывает этот элемент потоковой передачи в объект XmlWriter. |