0

XML を取り除き、必要なノードのみを保持しようとしています

入力 XML は

 <Employees>
  <Employee>
    <EmpId>1</EmpId>
    <Name>Sam</Name>
    <Sex>Male</Sex>
    <Address>
      <Country>USA</Country>
      <Zip>95220</Zip>
    </Address>
    <Address2>
      <Country>UK</Country>
      <Zip>E157JQ</Zip>
    </Address2>
  </Employee>
  <Employee>
    <EmpId>2</EmpId>
    <Name>Lucy</Name>
    <Sex>Female</Sex>
    <Address>
      <Country>USA</Country>
      <Zip>95220</Zip>
    </Address>
    <Address2>
      <Country>UK</Country>
      <Zip>E184JQ</Zip>
    </Address2>
  </Employee>
</Employees>

私のコードは以下の通りです。

private void button1_Click(object sender, EventArgs e)
    {
        Stream s = openFileDialog1.OpenFile();
        var xDoc = XDocument.Load(s);
        string keep = "EmpId,Sex,Address,Zip,Address2,Country"; \\ I can change this format
        string desStr = "Employee";
            string[] strArr = keep.Split(',');

            var nodesToDelete = xDoc.Root.Descendants(desStr)
                .SelectMany(el => el.Descendants()
                                  .Where(a => !strArr.Contains(a.Name.ToString())));

            foreach (var node in nodesToDelete.ToList())
                node.Remove();

            richTextBox1.Text = xDoc.ToString();
    }

私が上から得た出力は

<Employees>
      <Employee>
        <EmpId>1</EmpId>
        <Sex>Male</Sex>
        <Address>
          <Country>USA</Country>
          <Zip>95220</Zip>
        </Address>
        <Address2>
          <Country>UK</Country>
          <Zip>E157JQ</Zip>
        </Address2>
      </Employee>
      <Employee>
        <EmpId>2</EmpId>
        <Sex>Female</Sex>
        <Address>
          <Country>USA</Country>
          <Zip>95220</Zip>
        </Address>
        <Address2>
          <Country>UK</Country>
          <Zip>E184JQ</Zip>
        </Address2>
      </Employee>
    </Employees>

私が必要とする出力は

<Employees>
  <Employee>
    <EmpId>1</EmpId>
    <Sex>Male</Sex>
    <Address>
     <Zip>95220</Zip>
    </Address>
    <Address2>
      <Country>UK</Country>
    </Address2>
  </Employee>
  <Employee>
    <EmpId>2</EmpId>
    <Sex>Female</Sex>
    <Address>
      <Zip>95220</Zip>
    </Address>
    <Address2>
      <Country>UK</Country>
    </Address2>
  </Employee>
</Employees>

Address\Zip および Address2\Country を照会するにはどうすればよいですか。これを汎用にする必要があるため (したがって、文字列の保持を変更できます)、ノード名をハードコードすることはできません。

ありがとう

4

2 に答える 2

0

それは、これをどれだけジェネリックにしたいかによって異なります。これは、現在のコード構造を維持するためのややハックな方法です。

string keep = @"EmpId,Sex,Address,Address\Zip,Address2,Address2\Country";
string desStr = "Employee";
string[] strArr = keep.Split(',');

var nodesToDelete = xDoc.Root.Descendants(desStr)
                .SelectMany(el => el.Descendants()
                                  .Where(a => 
                                    {
                                        if (a.Parent.Name == desStr)
                                        {
                                            return !strArr.Contains(a.Name.ToString());
                                        }
                                        else
                                        {
                                            return !strArr.Contains(a.Parent.Name + @"\" + a.Name);
                                        }

                                    }));

foreach (var node in nodesToDelete.ToList())
      node.Remove();

適切な方法は、保持したいすべてのノードへの完全なパスを保持することです。

于 2013-10-28T12:49:38.550 に答える
0

私のやり方:

string keep = "Employees,Employee,EmpId,Sex,Address2,Address,Address.Zip,Address2.Country"; // I can change this format
string[] strArr = keep.Split(',');

    foreach (var node in xDoc.Descendants().ToArray())
    {
        var path = Path(node);
        if (!strArr.Any(path.EndsWith))
        {
            node.Remove();
        }
    }

    var results = xDoc.ToString();
}

private static string Path(XElement x)
{
    if (x.Parent != null)
    {
        return Path(x.Parent) + "." + x.Name;
    }

    return x.Name.ToString();
}
于 2013-10-28T13:03:46.027 に答える