body
아래 코드에서 혼합 요소 의 내용을 얻는 가장 좋은 방법은 무엇입니까 ? 요소에 XHTML 또는 텍스트가 포함될 수 있지만 내용을 문자열 형식으로 원합니다. XmlElement
유형은 가지고 InnerXml
난 후 정확히 무엇 속성을.
작성된 코드는 거의 내가 원하는 않지만, 주변 포함 <body>
… </body>
내가 원하지 않는 요소를.
XDocument doc = XDocument.Load(new StreamReader(s));
var templates = from t in doc.Descendants("template")
where t.Attribute("name").Value == templateName
select new
{
Subject = t.Element("subject").Value,
Body = t.Element("body").ToString()
};
답변
제안 된 솔루션 중 어떤 것이 가장 잘 수행되는지 확인하고 싶었 기 때문에 비교 테스트를 수행했습니다. 관심이 없으면 LINQ 메서드를 Greg가 제안한 일반 구형 System.Xml 메서드 와 비교했습니다 . 가장 느린 방법 은 가장 빠른 방법 보다 3 배 이상 느린 변형이 흥미롭고 예상했던 것과 다릅니다. .
결과는 가장 빠르거나 느리게 정렬됩니다.
- CreateReader-인스턴스 헌터 (0.113 초)
- 평범한 오래된 System.Xml-Greg Hurlman (0.134 초)
- 문자열 연결로 집계-Mike Powell (0.324 초)
- StringBuilder-Vin (0.333 초)
- String.Join on array-Terry (0.360 초)
- 배열의 문자열-Marcin Kosieradzki (0.364)
방법
20 개의 동일한 노드 ( ‘힌트’라고 함)가있는 단일 XML 문서를 사용했습니다.
<hint>
<strong>Thinking of using a fake address?</strong>
<br />
Please don't. If we can't verify your address we might just
have to reject your application.
</hint>
위의 초로 표시된 숫자는 20 개 노드의 “내부 XML”을 1000 회 연속으로 추출하여 평균 (평균) 5 회 실행 한 결과입니다. XML을로드하고 XmlDocument
( System.Xml 메서드의 경우) 구문 분석하는 데 걸리는 시간은 포함하지 않았습니다.XDocument
(다른 모든 것의 경우 .
내가 사용한 LINQ 알고리즘은 다음과 같습니다. (C #-모두 XElement
“부모”를 취하고 내부 XML 문자열을 반환합니다)
리더 만들기 :
var reader = parent.CreateReader();
reader.MoveToContent();
return reader.ReadInnerXml();
문자열 연결로 집계 :
return parent.Nodes().Aggregate("", (b, node) => b += node.ToString());
StringBuilder :
StringBuilder sb = new StringBuilder();
foreach(var node in parent.Nodes()) {
sb.Append(node.ToString());
}
return sb.ToString();
배열의 String.Join :
return String.Join("", parent.Nodes().Select(x => x.ToString()).ToArray());
배열의 String.Concat :
return String.Concat(parent.Nodes().Select(x => x.ToString()).ToArray());
노드에서 .InnerXml을 호출하기 때문에 여기에 “Plain old System.Xml”알고리즘을 표시하지 않았습니다.
결론
성능이 중요한 경우 (예 : 많은 XML, 자주 구문 분석) 매번 Daniel의 CreateReader
방법을 사용 합니다 . 몇 가지 쿼리를 수행하는 경우 Mike의 더 간결한 집계 방법을 사용할 수 있습니다.
많은 노드 (아마도 100)가있는 큰 요소에서 XML을 사용하는 경우 아마도 StringBuilder
Aggregate 메서드 를 사용하는 것의 이점을 볼 수 있지만 over는 아닙니다 CreateReader
. 큰 목록을 큰 배열로 변환하는 것에 대한 패널티 (여기서는 작은 목록에서는 명백 함)로 인해 이러한 조건에서 Join
및 Concat
메소드가 더 효율적 이라고 생각하지 않습니다 .
답변
나는 이것이 훨씬 더 나은 방법이라고 생각합니다 (VB에서는 번역하기가 어렵지 않아야 함).
XElement x가 주어지면 :
Dim xReader = x.CreateReader
xReader.MoveToContent
xReader.ReadInnerXml
답변
XElement에서이 “확장”방법을 사용하는 것은 어떻습니까? 나를 위해 일했다!
public static string InnerXml(this XElement element)
{
StringBuilder innerXml = new StringBuilder();
foreach (XNode node in element.Nodes())
{
// append node's xml string to innerXml
innerXml.Append(node.ToString());
}
return innerXml.ToString();
}
또는 Linq를 조금 사용하십시오
public static string InnerXml(this XElement element)
{
StringBuilder innerXml = new StringBuilder();
doc.Nodes().ToList().ForEach( node => innerXml.Append(node.ToString()));
return innerXml.ToString();
}
참고 : 위 코드는 element.Nodes()
반대로 사용해야 합니다 element.Elements()
. 둘 사이의 차이점을 기억하는 것이 매우 중요합니다. element.Nodes()
당신처럼 모든 것을 제공 XText
, XAttribute
등,하지만 XElement
단지 요소.
답변
최상의 접근 방식을 발견하고 입증 한 사람들에게 모든 정당한 인정을 받았으므로 (감사합니다!) 확장 방법으로 싸여 있습니다.
public static string InnerXml(this XNode node) {
using (var reader = node.CreateReader()) {
reader.MoveToContent();
return reader.ReadInnerXml();
}
}
답변
간단하고 효율적으로 유지하십시오.
String.Concat(node.Nodes().Select(x => x.ToString()).ToArray())
- 집계는 문자열을 연결할 때 메모리 및 성능 비효율적입니다
- Join ( “”, sth)을 사용하면 Concat보다 두 배 더 큰 문자열 배열을 사용하고 있습니다. 코드에서 매우 이상하게 보입니다.
- + =를 사용하는 것은 매우 이상해 보이지만 ‘+’를 사용하는 것보다 그리 나쁘지는 않습니다. 아마도 동일한 코드에 최적화 될 것입니다. 할당 결과가 사용되지 않고 컴파일러에 의해 안전하게 제거 될 수 있습니다.
- StringBuilder는 매우 필수적입니다. 모든 사람은 불필요한 “상태”가 짜증나다는 것을 알고 있습니다.
답변
나는 이것을 사용하여 끝났다.
Body = t.Element("body").Nodes().Aggregate("", (b, node) => b += node.ToString());
답변
개인적으로 InnerXml
Aggregate 메소드를 사용하여 확장 메소드를 작성했습니다 .
public static string InnerXml(this XElement thiz)
{
return thiz.Nodes().Aggregate( string.Empty, ( element, node ) => element += node.ToString() );
}
내 클라이언트 코드는 이전 System.Xml 네임 스페이스와 마찬가지로 간결합니다.
var innerXml = myXElement.InnerXml();