Как преобразовать многозначные XML-данные в DataSet? - PullRequest
1 голос
/ 19 мая 2010

У меня есть XML-документ с коллекцией объектов. Каждый объект имеет пару ключ / значение метки и значения. Я пытаюсь преобразовать это в DataSet, но когда я делаю ds.ReadXml (xmlFile), он создает два столбца: метка и значение.

Я хотел бы иметь столбец для каждой метки и значение, которое будет частью строки. Вот мой образец XML:

<responses>
  <response>
    <properties id="1" Form="Account Request" Date="Tuesday, March 16, 2010 5:04:26 PM" Confirmation="True" />
    <fields>
      <field>
        <label>Name</label>
        <value>John</value>
      </field>
      <field>
        <label>Email</label>
        <value>John@Doe.com</value>
      </field>
      <field>
        <label>Website</label>
        <value>http://domain1.com</value>
      </field>
      <field>
        <label>Phone</label>
        <value>999-999-9999</value>
      </field>
      <field>
        <label>Place of Birth</label>
        <value>Earth</value>
      </field>
      <field>
        <label>Misc</label>
        <value>Misc</value>
      </field>
      <field>
        <label>Comments</label>
        <value />
      </field>
      <field>
        <label>Agree to Terms?</label>
        <value>True</value>
      </field>
    </fields>
  </response>
  <response>
    <properties id="2" Form="Account Request" Date="Tuesday, March 17, 2010 5:04:26 PM" Confirmation="True" />
    <fields>
      <field>
        <label>Name</label>
        <value>John2</value>
      </field>
      <field>
        <label>Email</label>
        <value>John2@Doe.com</value>
      </field>
      <field>
        <label>Website</label>
        <value>http://domain2.com</value>
      </field>
      <field>
        <label>Phone</label>
        <value>999-999-9999</value>
      </field>
      <field>
        <label>Place of Birth</label>
        <value>Earth</value>
      </field>
      <field>
        <label>Misc</label>
        <value>Misc</value>
      </field>
      <field>
        <label>Comments</label>
        <value />
      </field>
      <field>
        <label>Agree to Terms?</label>
        <value>True</value>
      </field>
    </fields>
  </response>
  <response>
    <properties id="3" Form="Account Request" Date="Tuesday, March 18, 2010 5:04:26 PM" Confirmation="True" />
    <fields>
      <field>
        <label>Name</label>
        <value>John3</value>
      </field>
      <field>
        <label>Email</label>
        <value>John3@Doe.com</value>
      </field>
      <field>
        <label>Website</label>
        <value>http://domain3.com</value>
      </field>
      <field>
        <label>Phone</label>
        <value>999-999-9999</value>
      </field>
      <field>
        <label>Place of Birth</label>
        <value>Earth</value>
      </field>
      <field>
        <label>Misc</label>
        <value>Misc</value>
      </field>
      <field>
        <label>Comments</label>
        <value />
      </field>
      <field>
        <label>Agree to Terms?</label>
        <value>True</value>
      </field>
    </fields>
  </response>
  <response>
    <properties id="4" Form="Account Request" Date="Tuesday, March 19, 2010 5:04:26 PM" Confirmation="True" />
    <fields>
      <field>
        <label>Name</label>
        <value>John</value>
      </field>
      <field>
        <label>Email</label>
        <value>John4@Doe.com</value>
      </field>
      <field>
        <label>Website</label>
        <value>http://domain4.com</value>
      </field>
      <field>
        <label>Phone</label>
        <value>999-999-9999</value>
      </field>
      <field>
        <label>Place of Birth</label>
        <value>Earth</value>
      </field>
      <field>
        <label>Misc</label>
        <value>Misc</value>
      </field>
      <field>
        <label>Comments</label>
        <value />
      </field>
      <field>
        <label>Agree to Terms?</label>
        <value>True</value>
      </field>
    </fields>
  </response>
</responses>

Как мне преобразовать это в DataSet, чтобы я мог загрузить его в сетку со столбцами: Имя, Электронная почта, Веб-сайт, Телефон, Место рождения, Разное, Комментарии и Согласие с условиями?

Тогда строка 1 будет: Джон, John@Doe.com, http://domain1.com, 999-999-9999, Земля, Разное, Правда

Как я могу сделать это с предоставленным XML?

Ответы [ 3 ]

1 голос
/ 19 мая 2010

Вам придется трансформировать ваши данные, чтобы использовать их так, как вы хотите. Как вы видели, у вас плохая структура.

Я предлагаю вам создать пустой набор данных в Visual Studio (из Add-> New Item), а затем настроить его так, как вы хотите. Напишите некоторый код, чтобы добавить немного тестовых данных, затем запишите его в файл, используя DataSet.WriteXml. Это покажет вам, как будет выглядеть ваша предложенная структура.

Затем я рекомендую использовать LINQ to XML для преобразования входного XML в новый формат.


Вот пример использования LINQ to XML для преобразования ваших данных:

public static void TransformIt(TextWriter output)
{
    var inputDocument = XDocument.Parse(INPUT_XML);
    if (inputDocument.Root == null)
    {
        return;
    }

    var doc = new XDocument(
        new XElement(
            "responses",
            from response in inputDocument.Root.Elements()
            select new XElement(
                "response",
                from lv in GetResponseLabels(response)
                select MakeResponse(lv.Label, lv.Value))));

    var settings = new XmlWriterSettings
    {
        Encoding = Encoding.UTF8,
        Indent = true,
    };
    using (var writer = XmlWriter.Create(output, settings))
    {
        if (writer == null)
        {
            return;
        }

        doc.WriteTo(writer);
    }
}

private static XElement MakeResponse(string label, string value)
{
    var trimmedLabel = label.Replace(" ", String.Empty).Replace("?", String.Empty);
    return new XElement(trimmedLabel, value);
}

private static IEnumerable<LabelAndValue> GetResponseLabels(XContainer response)
{
    var fieldsElement = response.Element("fields");
    if (fieldsElement == null)
    {
        return null;
    }

    return from field in fieldsElement.Elements("field")
           let valueElement = field.Element("value")
           let labelElement = field.Element("label")
           select new LabelAndValue
           {
               Label = labelElement == null ? "Unknown" : labelElement.Value,
               Value = valueElement == null ? null : valueElement.Value
           };
}

private struct LabelAndValue
{
    public string Label { get; set; }
    public string Value { get; set; }
}
0 голосов
/ 20 мая 2010

Я немного изменил подход и сделал это (разворот):

DataRow dr = dt.NewRow();

//TRANSFORM RESPONSE LABELS INTO COLUMNS
foreach (XmlNode fieldNode in currentXml.SelectNodes("response/fields/field"))
{
    string label = fieldNode.SelectSingleNode("label").InnerText ?? "Unknown";
    string value = fieldNode.SelectSingleNode("value").InnerText;
    //CHECK IF ARBITRARY LABEL WAS ADDED BEFORE
    if (!dt.Columns.Contains(label))
    {
        //CREATE COLUMN FOR NEW LABEL
        dt.Columns.Add(label);
    }
    dr[label] = value;
}
dt.Rows.Add(dr);
}
ds.Tables.Add(dt);
0 голосов
/ 19 мая 2010

Я бы перебирал XML и в зависимости от того, как вы перебираете (Linq наиболее гибок), создаю новый объект (например, с данными) с вашими данными, описанными так, как вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...