2017-12-29 54 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文字列を取得して、どのようにして評価するか、同じ最終結果を達成する別の方法?

EDIT:私の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

関連する問題