0

次の情報を含むユーザー提供のDataTableがあります。

| Name      | Alias        |
|---------------------------
| Batman    | Dark Knight  |
| Superman  | Man of Steel |
| Spiderman | null         |

このテーブルをXmlに変換して、ストアドプロシージャに送信し、次のようなXmlを取得する必要があります。

<Superheroes>
    <Superhero Name="Batman" Alias="Dark Knight"/>
    <Superhero Name="Superman" Alias="Man of Steel"/>
    <Superhero Name="Spiderman"/>
</Superheroes>

この問題を解決するために、Linq-to-Xml(学習目的)を使用したいと思います。これが私がこれまでに持っているものです:

XDocument doc;

doc = new XDocument(
        new XElement("Superheroes",
        from row in table.AsEnumerable()
            select new XElement("Superhero",
                new XAttribute("Name", row.Field<string>("Name")),
                new XAttribute("Alias", row.Field<string>("Alias"))
)));

問題はスパイダーマンの列です。nullが原因で、上記のクエリは機能しません。

質問

  1. Linq-to-Xmlでnullスパイダーマン行を処理するにはどうすればよいですか?

  2. ユーザーがエイリアス行を追加するのを忘れた場合、私はそのサイトを処理できる必要があります。その場合、エイリアスは(a)Xmlにまったく含まれていないか、(b)値が空である必要があります。

4

3 に答える 3

2

XAttributeまたはを返すヘルパー関数を作成できますnull。Linq to XMLは、を無視しnullます。

private XAttribute GetAlias(DataRow row)
{
    if(row.Field<string>("Alias") != null)
    {
        return new XAttribute("Alias", row.Field<string>("Alias"));
    }
    return null;
}

そして、このように使用します。

doc = new XDocument(
    new XElement("Superheroes",
    from row in table.AsEnumerable()
        select new XElement("Superhero",
            new XAttribute("Name", row.Field<string>("Name")),
            GetAlias(row)
)));

これは、Alias列が欠落している場合にも機能するはずです。これは、列が欠落している場合にField<T>(string)拡張メソッドが返さnullれるためです。

または、列が欠落している場合や値が空の場合に属性を空の文字列にしたい場合はnull、次のようにすることができます。

doc = new XDocument(
    new XElement("Superheroes",
    from row in table.AsEnumerable()
        select new XElement("Superhero",
            new XAttribute("Name", row.Field<string>("Name")),
            new XAttribute("Alias", row.Field<string>("Alias") ?? string.Empty)
)));
于 2013-03-13T16:15:33.390 に答える
1

属性名を列のキャプションと同じにする必要がある場合のもう1つの解決策。null値を持たない属性のみを追加できます。

doc = new XDocument(
         new XElement("Superheroes",
            from row in table.AsEnumerable()
            select new XElement("Superhero",
                from column in table.Columns.Cast<DataColumn>()
                let value = row.Field<string>(column)
                where value != null // just filter out nulls
                select new XAttribute(column.Caption, value)
        )));

ところで、スパイダーマンはバットマンやスーパーマンほど良くはありません


実際には、次の拡張機能を作成できます。これにより、テーブル名と列名に基づいて任意のDataTableからxmlが構築されます(System.Data.Entity.DesignアセンブリのPluralizationServiceが必要です)。

public static class Extensions
{
    public static XDocument ToXml(this DataTable table)
    {
        if (String.IsNullOrEmpty(table.TableName))
           throw new ArgumentException("Table name is required");

        var pluralizationService = PluralizationService
                .CreateService(new CultureInfo("en-US"));
        string elementName = pluralizationService.Singularize(table.TableName);

        return new XDocument(
            new XElement(table.TableName,
                from row in table.AsEnumerable()
                select new XElement(elementName,
                    from column in table.Columns.Cast<DataColumn>()
                    let value = row.Field<string>(column)
                    where value != null
                    select new XAttribute(column.Caption, value)
                    )
                )
            );
    }
}

使い方は簡単です:

DataTable table = new DataTable("Superheroes"); // name is required
table.Columns.Add("Name");
table.Columns.Add("Alias");
table.Rows.Add("Batman", "Dark Knight");
table.Rows.Add("Superman", "Man Of Steel");
table.Rows.Add("Spiderman", null);
var doc = table.ToXml();

そして結果はかなりいいです

<Superheroes>
  <Superhero Name="Batman" Alias="Dark Knight" />
  <Superhero Name="Superman" Alias="Man Of Steel" />
  <Superhero Name="Spiderman" />
</Superheroes>
于 2013-03-13T17:30:00.057 に答える
0

インラインifステートメントを使用して(?:演算子Aliasを使用して)クエリを拡張し、が現在の行に設定されているかどうかを確認できます。

doc = new XDocument(
        new XElement("Superheroes",
        from row in table.AsEnumerable()
        select new XElement("Superhero",
            new XAttribute("Name", row.Field<string>("Name")),
            (row.Field<string>("Alias") != null ? new XAttribute("Alias", row.Field<string>("Alias")) : null))
));

返すnullと、生成されたXMLはまったく変更されないため、doc必要なものが正確に含まれます。

<Superheroes>
  <Superhero Name="Batman" Alias="Dark Knight" />
  <Superhero Name="Superman" Alias="Man of Steel" />
  <Superhero Name="Spiderman" />
</Superheroes>
于 2013-03-13T17:06:40.567 に答える