XElement의 InnerXml을 얻는 가장 좋은 방법은?
입니까의 입니까?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 방법을 평이한 구 시스템과 비교해 보았습니다.그렉이 제안한 xml 방법.가장 느린 방법이 가장 빠른 방법보다 3배 이상 느린 등 변화가 흥미로웠고 기대했던 것과는 다릅니다.
가장 빠른 순서에서 가장 느린 순서로 정렬된 결과:
- CreateReader - InstanceHunter(0.113초)
- 일반적인 오래된 시스템.Xml - 그렉 헐먼(0.134초)
- 문자열 연결이 있는 집계 - Mike Powell (0.324초)
- StringBuilder - Vin (0.333초)
- String.배열에 참여 - Terry(0.360초
- String.Concaton 배열 - 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번의 런의 평균(평균)을 취한 결과입니다.에 로드하고 분석하는 데 .XmlDocument(시스템의 경우).Xml 메서드) 또는XDocument(다른 모든 것에 대해서는)
제가 사용한 LINQ 알고리즘은 다음과 같습니다. (C# - 모두 "부모"를 취하고 내부 XML 문자열을 반환합니다.)
판독기 만들기:
var reader = parent.CreateReader();
reader.MoveToContent();
return reader.ReadInnerXml();
문자열 연결을 사용한 Aggregate:
return parent.Nodes().Aggregate("", (b, node) => b += node.ToString());
문자열 작성기:
StringBuilder sb = new StringBuilder();
foreach(var node in parent.Nodes()) {
sb.Append(node.ToString());
}
return sb.ToString();
String.배열에 가입:
return String.Join("", parent.Nodes().Select(x => x.ToString()).ToArray());
String.Concaton 배열:
return String.Concat(parent.Nodes().Select(x => x.ToString()).ToArray());
"평범한 오래된 시스템"을 보여주지 않았습니다.Xml" 알고리즘을 호출하는 중입니다.노드에 InnerXml이 있습니다.
결론
성능이 중요한 경우(예: XML을 많이 사용하고 자주 구문 분석하는 등), 매번 다니엘의 방법을 사용합니다.몇 가지 쿼리만 수행하는 경우 Mike의 보다 간결한 Aggregate 메서드를 사용할 수 있습니다.
요소을 사용하는 () 에서 XML 입니다를 수 것입니다.StringBuilderAggregate되지 않습니다.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();
}
아니면 약간의 린크를 사용합니다.
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())
- 문자열 연결 시 Aggregate의 메모리 및 성능이 비효율적임
- Join(",")을 사용하면 Concat보다 2배 큰 문자열 배열을 사용할 수 있습니다.코드상으로는 꽤 이상하게 보입니다.
- +=를 사용하는 것은 매우 이상해 보이지만 '+'를 사용하는 것보다 훨씬 나쁘지는 않습니다. 아마도 할당 결과가 사용되지 않고 컴파일러에 의해 안전하게 제거될 수 있기 때문에 동일한 코드에 최적화되어 있을 것입니다.
- StringBuilder는 매우 중요하며, 불필요한 "상태"가 엉망이라는 것은 모두가 알고 있습니다.
결국 이걸 쓰게 됐습니다.
Body = t.Element("body").Nodes().Aggregate("", (b, node) => b += node.ToString());
는 개인적으로 .InnerXmlAggregate 메서드를 사용하는 확장 메서드:
public static string InnerXml(this XElement thiz)
{
return thiz.Nodes().Aggregate( string.Empty, ( element, node ) => element += node.ToString() );
}
그러면 제 클라이언트 코드는 이전 시스템에서와 마찬가지로 더 간결합니다.XML 네임스페이스:
var innerXml = myXElement.InnerXml();
@그렉: 완전히 다른 답변이 되도록 답변을 편집하신 것 같네요.제 대답은 '그렇다' 입니다. 저는 시스템을 사용하여 이를 수행할 수 있습니다.Xml 하지만 내 발을 XML로 LINQ에 젖게 하고 있습니다.
XElement's만 사용할 수 없는 이유가 무엇인지 다른 사람들이 궁금해 할 경우를 대비하여 제 원래 답변을 아래에 남겨두겠습니다.필요한 것을 얻을 수 있는 소중한 자산:
@Greg: Value 속성은 자식 노드의 모든 텍스트 내용을 연결합니다.따라서 본문 요소에 텍스트만 포함되어 있으면 작동하지만 XHTML이 포함되어 있으면 모든 텍스트를 연결하고 태그는 연결하지 않습니다.
// Regex를 사용하면 시작 및 종료 요소 태그를 간단히 자를 수 있습니다.
var content = element.ToString();
var matchBegin = Regex.Match(content, @"<.+?>");
content = content.Substring(matchBegin.Index + matchBegin.Length);
var matchEnd = Regex.Match(content, @"</.+?>", RegexOptions.RightToLeft);
content = content.Substring(0, matchEnd.Index);
doc.ToString() 또는 doc.ToString(저장 옵션)이 작동합니다.http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.tostring(v=vs.110).aspx 참조
시스템을 사용할 수 있습니까?LINQ를 사용하지 않고 여기서 작업을 수행하려면 xml 네임스페이스 개체를 사용하시겠습니까?XmlNode는 이미 말씀하셨듯이,InnerXml이 바로 필요합니다.
혹시 (notice b+=를 없애고 b+만 있으면 됩니다)
t.Element( "body" ).Nodes()
.Aggregate( "", ( b, node ) => b + node.ToString() );
보다 약간 덜 효율적일 수도 있습니다.
string.Join( "", t.Element.Nodes()
.Select( n => n.ToString() ).ToArray() );
100% 확실하지는 않아요...Aggregate()와 문자열을 힐끗 쳐다보았습니다.반사판에 가입()...Aggregate가 반환 값을 추가하는 것으로 읽었으므로 기본적으로 다음을 얻을 수 있습니다.
문자열 = 문자열 + 문자열
줄 대 줄로가입하세요. 여기에 FastStringAllocation 같은 것이 언급되어 있습니다. 마이크로소프트 직원들이 추가적인 성능 향상을 위해 추가적인 노력을 기울였을 수도 있습니다.그럼요.To Array()는 제가 부정적이라고 부르지만, 저는 그저 다른 제안을 하나 더 하려고 했습니다.
var innerXmlAsText= XElement.Parse(xmlContent)
.Descendants()
.Where(n => n.Name.LocalName == "template")
.Elements()
.Single()
.ToString();
당신을 위해 그 일을 할 것입니다.
public static string InnerXml(this XElement xElement)
{
//remove start tag
string innerXml = xElement.ToString().Trim().Replace(string.Format("<{0}>", xElement.Name), "");
////remove end tag
innerXml = innerXml.Trim().Replace(string.Format("</{0}>", xElement.Name), "");
return innerXml.Trim();
}
언급URL : https://stackoverflow.com/questions/3793/best-way-to-get-innerxml-of-an-xelement
'programing' 카테고리의 다른 글
| 루프에서 sscanf를 사용하는 방법? (0) | 2023.09.25 |
|---|---|
| microsoft.interop.excel셀포맷팅셀 (0) | 2023.09.25 |
| Java에서 Excel 차트 만들기 (0) | 2023.09.25 |
| 크기를 사용하더라도 오는 불필요한 가로 스크롤 바아 ag-grid에서 ColumnsToFit (0) | 2023.09.25 |
| GCC에 OpenMP 지정 (0) | 2023.09.25 |