노드를 사용한 프로그래밍(LINQ to XML)

XML 편집기, 변환 시스템 또는 보고서 작성기와 같은 프로그램을 작성해야 하는 LINQ to XML 개발자는 요소와 특성보다 세부적인 단위에서 작업하는 코드를 작성해야 하는 경우가 많습니다. LINQ to XML 개발자는 흔히 노드 수준에서 작업하여 텍스트 노드, 처리 명령 및 처리 주석을 조작해야 합니다. 이 문서에서는 노드 수준에서 프로그래밍 정보를 제공합니다.

예: XDocument 자식 노드의 Parent 속성 값을 null(으)로 설정

Parent 속성에는 부모 노드가 아니라 부모 XElement가 포함되어 있습니다. XDocument의 자식 노드에는 부모 XElement가 없습니다. 이러한 노드의 부모는 문서이므로 해당 노드의 Parent 속성은 null(으)로 설정됩니다.

다음은 이에 대한 예입니다.

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)

이 예제는 다음과 같은 출력을 생성합니다.

True
True

예: 텍스트를 추가하면 새 텍스트 노드를 만들 수도, 만들지 않을 수 있음

많은 XML 프로그래밍 모델에서 인접 텍스트 노드는 항상 병합됩니다. 이를 텍스트 노드의 표준화라고 합니다. LINQ to XML은 텍스트 노드를 정규화하지 않습니다. 동일한 요소에 두 텍스트 노드를 추가하는 경우 인접 텍스트 노드가 생성됩니다. 그러나 XText 노드가 아니라 문자열로 지정된 내용을 추가하는 경우 LINQ to XML에서는 인접 텍스트 노드를 사용하여 문자열을 병합할 수 있습니다. 다음은 이에 대한 예입니다.

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())

이 예제는 다음과 같은 출력을 생성합니다.

1
1
2

예: 텍스트 노드 값을 빈 문자열로 설정해도 노드는 삭제되지 않음

일부 XML 프로그래밍 모델에서 텍스트 노드는 빈 문자열을 포함하지 않도록 보장됩니다. 그 이유는 이러한 텍스트 노드가 XML의 serialization에 영향을 미치지 않기 때문입니다. 그러나 인접 텍스트 노드가 가능한 것과 동일한 이유로, 값을 빈 문자열로 설정하여 텍스트 노드에서 텍스트를 제거하는 경우 텍스트 노드 자체는 삭제되지 않습니다.

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)

이 예제는 다음과 같은 출력을 생성합니다.

>><<

예: 빈 텍스트 노드가 하나 있는 요소는 텍스트 노드가 없는 요소와 다르게 직렬화됨

요소에 빈 자식 텍스트 노드만 포함되어 있으면 <Child></Child>와 같은 긴 태그 구문으로 직렬화됩니다. 요소에 자식 노드가 포함되어 있지 않으면 <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)

이 예제는 다음과 같은 출력을 생성합니다.

<Child1></Child1>
<Child2 />

예: 네임스페이스가 LINQ to XML 트리의 특성임

네임스페이스 선언의 구문은 특성의 구문과 동일하지만 XSLT 및 XPath와 같은 일부 프로그래밍 인터페이스에서 네임스페이스 선언은 특성으로 간주되지 않습니다. 그러나 LINQ to XML에서 네임스페이스는 XML 트리에서 XAttribute 개체로 저장됩니다. 네임스페이스 선언이 포함된 요소의 특성을 반복하는 경우 네임스페이스 선언이 반환된 컬렉션의 항목 중 하나로 나타납니다. IsNamespaceDeclaration 속성은 특성이 네임스페이스 선언인지 여부를 나타냅니다.

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

이 예제는 다음과 같은 출력을 생성합니다.

xmlns="http://www.adventure-works.com"  IsNamespaceDeclaration:True
xmlns:fc="www.fourthcoffee.com"  IsNamespaceDeclaration:True
AnAttribute="abc"  IsNamespaceDeclaration:False

예: XPath 축 메서드는 XDocument의 자식 텍스트 노드를 반환하지 않음

LINQ to XML에서는 텍스트 노드에 공백만 포함되어 있는 경우 XDocument의 자식 텍스트 노드를 허용합니다. 그러나 XPath 개체 모델에서는 문서의 자식 노드로 공백을 포함하지 않으므로 Nodes 축을 사용하여 XDocument의 자식을 반복할 때 공백 텍스트 노드가 반환됩니다. 그러나 XPath 축 메서드를 사용하여 XDocument의 자식을 반복하는 경우에는 공백 텍스트 노드가 반환되지 않습니다.

// 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())

이 예제는 다음과 같은 출력을 생성합니다.

3
0

XDocument의 XML 선언 노드는 자식 노드가 아닌 속성임

XDocument의 자식 노드를 반복할 때 XML 선언 개체가 표시되지 않습니다. XML 선언 개체는 문서의 자식 노드가 아니라 문서의 속성입니다.

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())

이 예제는 다음과 같은 출력을 생성합니다.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Root />
1