Programování s uzly (LINQ to XML)
Vývojáři LINQ to XML, kteří potřebují psát programy, jako je editor XML, transformační systém nebo zapisovač sestavy, často potřebují kód, který funguje na jemněji členitosti než prvky a atributy. Často potřebují pracovat na úrovni uzlu, manipulovat s textovými uzly, pokyny ke zpracování a zpracovávat komentáře. Tento článek obsahuje informace o programování na úrovni uzlu.
Příklad: Hodnoty Parent
vlastností podřízených uzlů objektu XDocument jsou nastaveny na hodnotu null
Vlastnost Parent obsahuje nadřazený XElementuzel, nikoli nadřazený uzel. Podřízené XDocument uzly nemají žádné nadřazené XElementuzly . Nadřazený objekt je dokument, takže Parent vlastnost pro tyto uzly je nastavena na null
hodnotu .
Následující příklad ukazuje toto:
XDocument doc = XDocument.Parse(@"<!-- a comment --><Root/>");
Console.WriteLine(doc.Nodes().OfType<XComment>().First().Parent == null);
Console.WriteLine(doc.Root.Parent == null);
Dim doc As XDocument = XDocument.Parse("<!-- a comment --><Root/>")
Console.WriteLine(doc.Nodes().OfType(Of XComment).First().Parent Is Nothing)
Console.WriteLine(doc.Root.Parent Is Nothing)
Tento příklad vytvoří následující výstup:
True
True
Příklad: Přidání textu může nebo nemusí vytvořit nový textový uzel
V řadě programovacích modelů XML se sousední textové uzly vždy sloučí. Někdy se tomu říká normalizace textových uzlů. LINQ to XML nenormalizuje textové uzly. Pokud ke stejnému prvku přidáte dva textové uzly, výsledkem budou sousední textové uzly. Pokud ale přidáte obsah zadaný jako řetězec, ne jako XText uzel, může LINQ to XML sloučit řetězec s sousedním textovým uzlem. Následující příklad ukazuje to.
XElement xmlTree = new XElement("Root", "Content");
Console.WriteLine(xmlTree.Nodes().OfType<XText>().Count());
// this doesn't add a new text node
xmlTree.Add("new content");
Console.WriteLine(xmlTree.Nodes().OfType<XText>().Count());
// this does add a new, adjacent text node
xmlTree.Add(new XText("more text"));
Console.WriteLine(xmlTree.Nodes().OfType<XText>().Count());
Dim xmlTree As XElement = <Root>Content</Root>
Console.WriteLine(xmlTree.Nodes().OfType(Of XText)().Count())
' This doesn't add a new text node.
xmlTree.Add("new content")
Console.WriteLine(xmlTree.Nodes().OfType(Of XText)().Count())
'// This does add a new, adjacent text node.
xmlTree.Add(New XText("more text"))
Console.WriteLine(xmlTree.Nodes().OfType(Of XText)().Count())
Tento příklad vytvoří následující výstup:
1
1
2
Příklad: Nastavení hodnoty textového uzlu na prázdný řetězec neodstraní uzel.
V některých programovacích modelech XML je zaručeno, že textové uzly neobsahují prázdný řetězec. Důvodem je, že takový textový uzel nemá žádný vliv na serializaci XML. Pokud ale z textového uzlu odeberete text z textového uzlu tak, že nastavíte jeho hodnotu na prázdný řetězec, samotný textový uzel se neodstraní.
XElement xmlTree = new XElement("Root", "Content");
XText textNode = xmlTree.Nodes().OfType<XText>().First();
// the following line doesn't cause the removal of the text node.
textNode.Value = "";
XText textNode2 = xmlTree.Nodes().OfType<XText>().First();
Console.WriteLine(">>{0}<<", textNode2);
Dim xmlTree As XElement = <Root>Content</Root>
Dim textNode As XText = xmlTree.Nodes().OfType(Of XText)().First()
' The following line doesn't cause the removal of the text node.
textNode.Value = ""
Dim textNode2 As XText = xmlTree.Nodes().OfType(Of XText)().First()
Console.WriteLine(">>{0}<<", textNode2)
Tento příklad vytvoří následující výstup:
>><<
Příklad: Prvek s jedním prázdným textovým uzlem je serializován odlišně od elementu bez textového uzlu.
Pokud prvek obsahuje pouze podřízený textový uzel, který je prázdný, je serializován s dlouhou syntaxí značky: <Child></Child>
. Pokud prvek neobsahuje žádné podřízené uzly vůbec, je serializován s krátkou syntaxí značky: <Child />
.
XElement child1 = new XElement("Child1",
new XText("")
);
XElement child2 = new XElement("Child2");
Console.WriteLine(child1);
Console.WriteLine(child2);
Dim child1 As XElement = New XElement("Child1", _
New XText("") _
)
Dim child2 As XElement = New XElement("Child2")
Console.WriteLine(child1)
Console.WriteLine(child2)
Tento příklad vytvoří následující výstup:
<Child1></Child1>
<Child2 />
Příklad: Obory názvů jsou atributy ve stromu LINQ to XML.
I když deklarace oboru názvů mají identickou syntaxi atributů, v některých programovacích rozhraních, jako jsou XSLT a XPath, se deklarace oborů názvů nepovažují za atributy. V LINQ to XML jsou však obory názvů uloženy jako XAttribute objekty ve stromu XML. Pokud iterujete atributy elementu, který obsahuje deklaraci oboru názvů, je deklarace oboru názvů jednou z položek ve vrácené kolekci. Vlastnost IsNamespaceDeclaration označuje, zda atribut je deklarace oboru názvů.
XElement root = XElement.Parse(
@"<Root
xmlns='http://www.adventure-works.com'
xmlns:fc='www.fourthcoffee.com'
AnAttribute='abc'/>");
foreach (XAttribute att in root.Attributes())
Console.WriteLine("{0} IsNamespaceDeclaration:{1}", att, att.IsNamespaceDeclaration);
Dim root As XElement = _
<Root
xmlns='http://www.adventure-works.com'
xmlns:fc='www.fourthcoffee.com'
AnAttribute='abc'/>
For Each att As XAttribute In root.Attributes()
Console.WriteLine("{0} IsNamespaceDeclaration:{1}", att, _
att.IsNamespaceDeclaration)
Next
Tento příklad vytvoří následující výstup:
xmlns="http://www.adventure-works.com" IsNamespaceDeclaration:True
xmlns:fc="www.fourthcoffee.com" IsNamespaceDeclaration:True
AnAttribute="abc" IsNamespaceDeclaration:False
Příklad: Metody osy XPath nevrací podřízené textové uzly XDocument.
LINQ to XML umožňuje podřízeným textovým uzlům , XDocumentpokud textové uzly obsahují pouze prázdné znaky. Objektový model XPath však neobsahuje prázdné znaky jako podřízené uzly dokumentu, takže při iteraci podřízenými XDocument položkami osy pomocí Nodes osy se vrátí prázdné textové uzly. Pokud však iterujete podřízené položky XDocument metody osy XPath, nebudou vráceny prázdné textové uzly.
// Create a document with some white space child nodes of the document.
XDocument root = XDocument.Parse(
@"<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<Root/>
<!--a comment-->
", LoadOptions.PreserveWhitespace);
// count the white space child nodes using LINQ to XML
Console.WriteLine(root.Nodes().OfType<XText>().Count());
// count the white space child nodes using XPathEvaluate
Console.WriteLine(((IEnumerable)root.XPathEvaluate("text()")).OfType<XText>().Count());
' Create a document with some white space child nodes of the document.
Dim root As XDocument = XDocument.Parse( _
"<?xml version='1.0' encoding='utf-8' standalone='yes'?>" & _
vbNewLine & "<Root/>" & vbNewLine & "<!--a comment-->" & vbNewLine, _
LoadOptions.PreserveWhitespace)
' Count the white space child nodes using LINQ to XML.
Console.WriteLine(root.Nodes().OfType(Of XText)().Count())
' Count the white space child nodes using XPathEvaluate.
Dim nodes As IEnumerable = CType(root.XPathEvaluate("text()"), IEnumerable)
Console.WriteLine(nodes.OfType(Of XText)().Count())
Tento příklad vytvoří následující výstup:
3
0
Uzel deklarace XML objektu XDocument je vlastnost, nikoli podřízený uzel.
Při iteraci podřízenými uzly objektu XDocumentdeklarace XML se nezobrazí. Jedná se o vlastnost dokumentu, nikoli podřízený uzel dokumentu.
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Root")
);
doc.Save("Temp.xml");
Console.WriteLine(File.ReadAllText("Temp.xml"));
// this shows that there is only one child node of the document
Console.WriteLine(doc.Nodes().Count());
Dim doc As XDocument = _
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<Root/>
doc.Save("Temp.xml")
Console.WriteLine(File.ReadAllText("Temp.xml"))
' This shows that there is only one child node of the document.
Console.WriteLine(doc.Nodes().Count())
Tento příklad vytvoří následující výstup:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Root />
1