2017-12-29 3 views
1

XML 문서 내에서 특정 값을 찾은 다음 특정 태그 이름을 가진 부모를 찾을 때까지 각 부모를 위쪽으로 반복합니다. 나는 데특정 태그를 찾을 때까지 루프 노드를 반복합니다.

List<XElement> fieldReferences = new List<XElement>(); 
fieldReferences.AddRange(element.XPathSelectElements(string.Format("descendant::nameValue[@idref='{0}']", fieldName))); 
fieldReferences.AddRange(element.XPathSelectElements(string.Format("descendant::nameValue[@value='{0}']", fieldName))); 

string parentIterator = ".Parent"; 
string attributeValue = ".Attribute('id').Value"; 
string parentElementName = ".Name"; 
foreach (var value in fieldReferences) 
{ 
    var parentField = string.Format("{0}{1}", parentIterator, parentElementName); 
    while (value + parentField != "private" || value + parentField != "public") 
     { 
      // keep appending .Parent until it finds what it needs 
     } 
    //var parentField = value.Parent.Parent.Parent.Parent.Attribute("id").Value; 
    outputFields.Add(parentField, name.FirstOrDefault()); 
} 

문제는 실제로 값의 .Parent.Name 속성을 확인 않을거야 그래서 parentField 항상 문자열로 평가 될 것입니다.

나는 C#으로 자주 작업하지 않기 때문에 이렇게하는 것이 훨씬 쉽습니다. 내 질문은 다음과 같습니다. parentField 문자열을 사용하여 원하는 방식을 평가하려면 어떻게해야합니까? 또는 어떻게해야합니까? 같은 결과를 얻는 다른 방법?

편집 : 내 XML이 어떻게 생겼는지. XPAthSelectElement는 nameValue 요소를 가져옵니다 그리고 내가

<private id="I need to iterate upwards through each parent element until I find this one"> 
    <value> 
     <request> 
     <nameValues> 
      <nameValue idref="I found this" /> 
      <nameValue value=""/> 
     </nameValues> 
     </request> 
    </value> 
    </private> 
+1

몇 차례 질문을 읽었으며 아직 시도하고있는 문제를 파악하고 있습니다. XML의 실제 예제와 일치시키려는 것들의 유형을 줄 수 있습니까? –

+0

XElement에는 또 다른 XElement를 제공하는 부모 속성이 있습니다. 그렇다면 왜 문자열로 변환해야합니까? https://msdn.microsoft.com/en-us/library/system.xml.linq.xelement_properties(v=vs.110).aspx. value.Parent는 당신에게 부모를주고, 거기서 부모에 대한 정보를 얻습니다. – Ctznkane525

+0

네, 미안하지만 설명하기가 조금 어렵습니다. – JOO

답변

1

그래서 당신은 실제로 다음 XPath에 미친 이동이 많은 문자열 작업을 수행 할 필요가 없습니다 개인 태그를 찾을 때까지 각 상위 요소를 통해 반복합니다. 자녀 타겟 요소를 찾으면 XElement이 비공개/공개 태그로 발견 될 때까지 속성을 XElement에 반복적으로 사용할 수 있습니다. 즉 우리가이 코드를 제공합니다 그래서 :

foreach (XElement element in fieldReferences) 
{ 
    XElement currentElement = element; 
    while (currentElement.Parent != null) 
    { 
     currentElement = currentElement.Parent; 
     if (currentElement.Name == "private" || currentElement.Name == "public") { 
      outputFields.Add(currentElement, /* not sure what you want here */); 
      break; 
     } 
    } 
} 

그래서 currentElement은 예로부터 nameValue 태그 요소로 시작합니다. while 루프에서 각 반복 currentElement은 상위 노드가 없거나 currentElementprivate 또는 public 태그가 될 때까지 상위 노드로 변경됩니다. 후자의 경우, 결과에 추가됩니다.

+0

는 foreach는 반복 변수가 이같이 말 때문에 요소에 할당 할 수 없습니다. – JOO

+0

나쁘지 만 단순히 새로운 변수에 할당 할 수 있습니다. 내 대답을 편집했습니다. –

+0

그래, 내가 그 일을 끝내고, 지금 시도해보고 너에게 알려 줄거야. – JOO

1

XElement.Ancestors 함수를 사용하면 찾은 노드가 포함 된 모든 요소의 목록을 가져온 다음 LINQ를 사용하여 원하는 노드를 선택할 수 있습니다. 루프가 필요 없습니다. 이 모든 방법까지 나무를 갈 것입니다, 여러 일치하는 조상 (또는 일치 조상)이있는 경우 문제가있을 수 있음을

var results = fieldReferences.Select(element => element.Ancestors() 
                 .Where(ancestor => ancestor.Name == "public" || 
                      ancestor.Name == "private") 
                 .FirstOrDefault()); 

참고. 그것이 당신에게 문제가되는지, 그리고 그 경우 당신이 원하는 결과가 무엇인지 알려주세요, 그리고 조정할 수 있습니다.

+0

이 접근법의 유일한 문제점은 내 fieldReferences 목록에 많은 항목이있을 수 있다는 것입니다. – JOO

+0

모든 요소에 대해 올바른 요소를 찾아야합니다. 그게 네가 원하는게 아니야? 'fieldReferences'가 3 개의'XElement' 인스턴스를 포함하면'results'는 "public"또는 "private"엘리먼트의 조상 인 3 개의'XElement' 인스턴스를 포함하게됩니다. –

+0

이제는 리팩토링 기회 목록에이 접근법을 추가 할 예정입니다. 감사합니다! – JOO

관련 문제