2

値がテーブルに入れられる製品の XmlNodeList があります。ここで、特定の製品が見つかったときに新しい XmlNode をリストに追加して、同じループで新しい製品がファイル内の元のアイテムと同じように扱われるようにします。この方法では、関数の構造を変更する必要はありません。次に処理されるノードを追加するだけです。しかし、XmlNode は抽象クラスであり、新しいノードをプログラムで作成する方法がわかりません。これは可能ですか?

XmlNodeList list = productsXml.SelectNodes("/portfolio/products/product");

for (int i = 0; i < list.Count; i++)
{
  XmlNode node = list[i];

  if (node.Attributes["name"].InnertText.StartsWith("PB_"))
  {
    XmlNode newNode = ????
    list.InsertAfter(???, node);
  }

  insertIntoTable(node);
}
4

2 に答える 2

14

XmlDocumentはそのノードのファクトリであるため、これを行う必要があります。

XmlNode newNode = document.CreateNode(XmlNodeType.Element, "product", "");

またはそのショートカット:

XmlNode newNode = document.CreateElement("product");

次に、新しく作成されたノードをその親に追加するには:

node.ParentNode.AppendChild(newNode);

追加されたノードを処理する必要がある場合は、明示的に処理する必要があります。ノード リストは、検索条件に一致したノードのスナップショットであり、動的に更新されません。insertIntoTable()追加されたノードを呼び出すだけです:

insertIntoTable(node.ParentNode.AppendChild(newNode));

コードが大きく異なる場合は、このプロセスを 2 ステップのバッチにするために少しリファクタリングが必要になる場合があります (最初に追加するノードを検索し、次にそれらすべてを処理します)。もちろん、完全に異なるアプローチに従うこともできます (たとえば、ノードを List からコピーXmlNodeListし、両方のリストに追加するなど)。

これで十分 (そしてリファクタリングは必要ない) と仮定して、すべてをまとめてみましょう。

foreach (var node in productsXml.SelectNodes("/portfolio/products/product"))
{
  if (node.Attributes["name"].InnertText.StartsWith("PB_"))
  {
    XmlNode newNode = document.CreateElement("product");
    insertIntoTable(node.ParentNode.AppendChild(newNode));
  }

  // Move this before previous IF in case it must be processed
  // before added node
  insertIntoTable(node);
}

リファクタリング

リファクタリング時間 (200 行の関数がある場合は、ここで提示したものよりもはるかに多くの時間が必要です)。あまり効率的ではない場合でも、最初のアプローチ:

var list = productsXml
    .SelectNodes("/portfolio/products/product")
    .Cast<XmlNode>();
    .Where(x.Attributes["name"].InnertText.StartsWith("PB_"));

foreach (var node in list)
    node.ParentNode.AppendChild(document.CreateElement("product"));

foreach (var node in productsXml.SelectNodes("/portfolio/products/product"))
    insertIntoTable(node); // Or your real code

2 パス アプローチが気に入らない場合は、次のように使用できますToList()

var list = productsXml
    .SelectNodes("/portfolio/products/product")
    .Cast<XmlNode>()
    .ToList();

for (int i=0; i < list.Count; ++i)
{
    var node = list[i];

    if (node.Attributes["name"].InnertText.StartsWith("PB_"))
      list.Add(node.ParentNode.AppendChild(document.CreateElement("product"))));

    insertIntoTable(node);
}

2 番目の例では、ループ内でコレクションを変更するため、for代わりにの使用が必須であることに注意してください。元のオブジェクトをforeachそのままにしておくこともできることに注意してください...XmlNodeList

于 2013-11-06T09:27:53.360 に答える
2

XmlNode を直接作成することはできませんが、親XmlDocumentの Create* メソッドのいずれかを使用して、サブタイプ (要素など) のみを作成できます。たとえば、新しい要素を作成する場合:

XmlElement el = doc.CreateElement("elementName");
node.ParentNode.InsertAfter(el, node);

これは要素を XmlNodeList リストに追加しないため、ノードは処理されないことに注意してください。したがって、ノードを追加するときに、ノードの必要なすべての処理を正しく実行する必要があります。

于 2013-11-06T09:28:19.143 に答える