2014-06-18 3 views
0

타사에서 보낸 xml이 있는데 유효성을 검사하고 싶습니다.LINQ to XML 필터 자손 C#

XElement xTree = XElement.Parse(@"<Container> 
    <TrackingReferences> 
     <TrackingReference> 
      <TrackingName>Donny</TrackingName> 
      <TrackingCodes> 
      <TrackingCode> 
       <Name></Name> 
      </TrackingCode> 
      <TrackingCode> 
       <Name>DisplayThis</Name> 
      </TrackingCode> 
      <TrackingCode> 
       <Name></Name> 
      </TrackingCode> 
      </TrackingCodes> 
     </TrackingReference> 
     </TrackingReferences> 
    </Container>"); 

IEnumerable<XElement> childList = xTree.Element("TrackingReferences").Descendants("TrackingReference").Where(
    tr => (
      tr.Element("TrackingName") != null && !tr.Element("TrackingName").IsEmpty && !String.IsNullOrEmpty(tr.Element("TrackingName").Value) && 
      tr.Descendants("TrackingCodes").Any(
       tc => tc.HasElements && 
        tc.Elements("TrackingCode").Any(
         code => code.Element("Name") != null && !code.Element("Name").IsEmpty && !String.IsNullOrEmpty(code.Element("Name").Value) 
        ) 
      ) 
    ) 
); 

내가 원하는 자손을 반환하는 방법을 알 수 없습니다.

내가 가진 문제는 내가 아니라 TrackingCode가 null 또는 비어 있지 않은 이름 요소가있을 때 TrackingReference 요소가 TrackingCode 후손을 포함 할 것입니다.

아래의 예는 반환이 값으로 이름 요소가로

<TrackingReference> 
    <TrackingName>Donny</TrackingName> 
    <TrackingCodes> 
    <TrackingCode> 
     <Name></Name> 
    </TrackingCode> 
    <TrackingCode> 
     <Name>DisplayThis</Name> 
    </TrackingCode> 
    <TrackingCode> 
     <Name></Name> 
    </TrackingCode> 
    </TrackingCodes> 
</TrackingReference> 

그러나이 예에서는 그냥 두 번째 요소가 반환되는 첫 번째와 세 번째 TrackingCode을 원하지 않는다 이 같은이 처음 내가 XML에 LINQ 쿼리를 쿼리가 더 깨끗하게 만드는 방법에 해당하므로, 어떠한 조언을 시도했습니다있다

<TrackingReference> 
     <TrackingName>Donny</TrackingName> 
     <TrackingCodes> 
     <TrackingCode> 
      <Name>DisplayThis</Name> 
     </TrackingCode> 
     </TrackingCodes> 
    </TrackingReference> 

/효율이 훨씬 apprecia 것 테드, 또는 내가이 일을 잘못하고 있다면. 이것은 당신이 호출하면 XElement에 명시 적 문자열 변환이 null을 반환한다는 사실을 사용

var query = doc.Descendants("TrackingReference") 
       // TODO: Filter based on TrackingName if you want... 
       .Descendants("TrackingCode") 
       .Where(x => !string.IsNullOrEmpty((string) x.Element("Name")); 

: 그것은 아주 쉽게 사실, 그래서 당신은, 오히려 TrackingReference 요소보다 TrackingCode 요소를 원하는처럼

+1

는 당신이 실제로 하시겠습니까 TrackingReference 요소의 수정 된 버전 또는 비어 있지 않은 이름을 가진 일련의 TrackingCode 요소에 만족하십니까? 후자는 훨씬 간단합니다. –

+0

트리밍 된 문서를 원한다면 Xsl 변환이이 문제에 더 잘 맞을 수 있습니까? – StuartLC

+0

@JonSkeet - 후자. 위의 예에서는 3 개의 TrackingCode 요소 대신 하나의 TrackingCode 요소가 반환됩니다 (쿼리가 현재 반환 됨). 고마워. – strangerinthealps

답변

2

좋아, 그것은 소리 그것은 null 피연산자로되어 있습니다. 당신은, 당신은 정체성 빈 TrackingCode의 변환을 제거 할 수있는 XSLT 솔루션을 고려할 않았다 그냥 경우

+0

TrackingReference 요소를 찾고 있었지만 TrackingRece 요소가있는 TrackingCode 자손을 가지고있었습니다. 비어 있지 않은 이름. 질문을 편집하여 내가 무엇을 반환했는지 보여주었습니다. 이론적으로 원본 xml에 많은 TrackingReference 요소가있을 수 있으므로 모든 필터를 실행하고 싶습니다. 명시 적 문자열 변환 팁. 도와 주셔서 감사합니다 – strangerinthealps

0

eat 빈 노드에 템플릿 :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" /> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="TrackingCode[not(Name)] | TrackingCode[Name='']"/> 
</xsl:stylesheet> 

XslCake fiddle here