2009-03-31 5 views
1

웹 서비스를 사용할 수 없습니다. 제어 할 수없고 해당 서비스에서 반환 한 XML을 표준 개체로 구문 분석하려고합니다.LINQ를 사용하여 XML 태그 모음을 문자열에 연결하십시오.

XML 구조의 일부가 결국이

<NO> 
    <L>Some text here </L> 
    <L>Some additional text here </L> 
    <L>Still more text here </L> 
</NO> 

처럼 보이는

, 나는 "여기에 일부 텍스트 여기에 몇 가지 여기에 추가 텍스트 여전히 더 많은 텍스트 모양을 하나 개의 문자열 속성을 끝내고 싶어 "

내가 처음으로 통과 한 내용은 다음과 같습니다. 나는 확실히 거기에 아직 내가 곧 정상 궤도에있어 생각하지만, :

XElement source = \\Output from the Webservice 
List<IndexEntry> result; 

result = (from indexentry in source.Elements(entryLevel) 
    select new IndexEntry() 
    { 
     EtiologyCode = indexentry.Element("IE") == null ? null : indexentry.Element("IE").Value, 
     //some code to set other properties in this object 
     Note = (from l in indexentry.Elements("NO").Descendants 
       select l.value) //This is where I stop 
           // and don't know where to go 
    } 

내가 컬렉션을 반환하는 쿼리 끝에 ToList() 연산자를 추가 할 수 있다는 것을 알고있다. 해당 컬렉션의 concatentation을 단일 문자열로 인라인 할 수있는 opertaor 또는 기술이 있습니까?

분명하지 않은 경우 더 많은 정보를 물어보십시오.

감사합니다.

답변

7

LINQ 실제로 여기에 방법입니다. 또 다른 대안은 별도의 확장 방법으로 추출하는 것입니다

result = (from indexentry in source.Elements(entryLevel) 
    select new IndexEntry 
    { 
     EtiologyCode = indexentry.Element("IE") == null 
          ? null 
          : indexentry.Element("IE").Value, 
     //some code to set other properties in this object 
     Note = string.Join(" ", indexentry.Elements("NO") 
              .Descendants() 
              .Select(x => x.Value) 
              .ToArray()) 
    }; 

(이것은 최고 수준의 정적 클래스에 있어야한다) : 그것은 다소 추한 경우, 쉽게

public static string ConcatenateTextNodes(
    this IEnumerable<XElement> elements) 
{ 
    string[] values = elements.Select(x => x.Value).ToArray(); 
    // You could parameterise the delimiter here if you wanted 
    return string.Join(" ", values); 
} 

는 다음 코드를 변경 로 :

result = (from indexentry in source.Elements(entryLevel) 
    select new IndexEntry 
    { 
     EtiologyCode = indexentry.Element("IE") == null 
          ? null 
          : indexentry.Element("IE").Value, 
     //some code to set other properties in this object 
     Note = indexentry.Elements("NO") 
         .Descendants() 
         .ConcatenateTextNodes() 
    } 

편집 : 효율성에 관한 참고

다른 답변은 효율성을 높이기 위해 StringBuilder을 사용하시기 바랍니다. 내가 이것을 사용하기 전에 갈 올바른 방법이라는 증거를 확인합니다. 그것에 대해 생각하면 StringBuilderToArray은 비슷한 일을합니다. 필요한 것보다 더 큰 버퍼를 만들고, 데이터를 추가하고, 필요할 때 크기를 조정하고, 결과가 나오는 것입니다. 희망은 너무 자주 크기를 조정할 필요가 없다는 것입니다.

StringBuilderToArray 사이의 차이 여기 버퍼링되고 있는지입니다 - StringBuilder에 당신이 지금까지 구축 한 문자열의 전체 내용입니다. ToArray이고, 바로는입니다. 즉, ToArray에 사용되는 내부 버퍼의 크기를 조정하면 StringBuilder, , 특히에 대한 크기를 조정하는 것보다 비용이 적게 듭니다. 개별 문자열이 긴 경우.

ToArray의 버퍼링을 수행 한 후, string.Join은 상당히 효율적이다 : 그것은, 시작하는 모든 문자열을 통해보고 를 해결할 수 정확히 할당하고 사상을 복사하지 않고도을 연결하는 공간이 얼마나 실제 문자 데이터.

이것은 sharp contrast to a previous answer I've given에 있습니다.하지만 불행히도 나는 벤치 마크를 작성한 적이 없다고 생각합니다.

내가 확실히 상당히 느린 것으로 ToArray을 기대하지 않을 것이다, 나는 그것을 여기에 코드를 간단하게 생각한다 - 등, 집계 등

+0

존은, 어쩌면 내 예제는 분명하지 않다. 더 복잡한 opject를 LINQ TO XML 쿼리로 채 웁니다. 이 예제는 관련된 XML의 일부만 나타냅니다. 따라서 아래쪽 예제에서 NOTE는 객체의 문자열 속성을 나타내며 가능하면 채울 수 있습니다. –

+0

... 나머지 LINQ 쿼리와 인라인을 유지합니다. 내가 분명하니? 나는 당신이 옹호하고 이해하는 것을보고, 나는 단지 내 상황에 그것을 적용하는 방법을 모르겠습니다. 도움이된다면 컨텍스트에 대한 코드를 더 추가 할 수 있습니다. –

+0

편집 대답 ... –

0

직접 경험 한 적은 없지만 LINQ to XML은 코드를 크게 단순화시킬 수 있다고 생각합니다. XML 문서를 선택하고 루프를 반복하며 StringBuilder를 사용하여 L 요소를 일부 문자열에 추가합니다.

var textArray = topElement.Elements("L") 
          .Select(x => x.Value) 
          .ToArray(); 

var text = string.Join(" ", textArray); 

편집은 : 당신은 그냥이를 표현하는 하나의 표현 방법이 필요 같은 의견을 바탕으로, 보이는 XML에

1

다른 옵션은 집계를 사용하는 것입니다 (부작용을 사용할 필요가 없습니다)

var q = topelement.Elements("L") 
        .Select(x => x.Value) 
        .Aggregate(new StringBuilder(), 
          (sb, x) => return sb.Append(x).Append(" "), 
          sb => sb.ToString().Trim()); 

편집 : 누계 제 람다는 어큐뮬레이터이다. 이것은 모든 가치관을 받아들이고 하나의 가치를 창출합니다. 이 경우 원하는 텍스트로 StringBuilder를 만듭니다. 두 번째 람다는 결과 선택자입니다. 이를 통해 누적 된 가치를 원하는 결과로 변환 할 수 있습니다. 이 경우 StringBuilder를 String으로 변경하십시오.

+0

이것은 내 대답 일 수 있습니다. 나는 그것을 시도 할 것이다, 고마워. –

+0

오, 예. 코드에서 'var q ='를 'Note ='로 바꿔야합니다. – dustyburwell

+0

확장 된 대답보기 - StringBuilder를 사용하면 string.Join과 ToArray를 함께 사용하여 성능을 향상시킬 수 있다고 생각하지 않습니다. 심지어 악화시킬 수도 있습니다. 확실히 IMO를 더 복잡하게 만듭니다. –

0

나는 LINQ를 다음 사람만큼 좋아하지만, 여기 바퀴를 다시 만들고 있습니다. XmlElement.InnerText 속성은 요청되는 것을 정확히 수행합니다.

이 시도 :

using System.Xml; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     XmlDocument d = new XmlDocument(); 
     string xml = 
      @"<NO> 
    <L>Some text here </L> 
    <L>Some additional text here </L> 
    <L>Still more text here </L> 
</NO>"; 
     d.LoadXml(xml); 
     Console.WriteLine(d.DocumentElement.InnerText); 
     Console.ReadLine(); 
    } 
} 
+0

그게 전부 좋겠지 만 좋겠지 만 LINQ를 사용하여 XML을 파싱하여 비즈니스 개체를 작성하고 XML의 유사한 구문을 사용하여 이러한 개체 내부에 컬렉션을 구축해야하므로 나중에 추가 처리가 필요하지 않습니다. 기존 LINQ 쿼리 내부에 유지하고 싶습니다. –

관련 문제