Преобразование DataSet в XML с вложенными элементами - PullRequest
1 голос
/ 01 апреля 2011

Я пишу WebService, который должен конвертировать DataSet в XML. Мой DataSet на самом деле список отелей с категориями. Каждый отель может принадлежать к одной или нескольким категориям. Я последовал примеру ЗДЕСЬ , и он работает хорошо, за исключением того, что я не получил желаемого результата.

Вот что я получаю: (пример 1)

<hotels>
    <hotel>
        <name>Hilton Resort</name>
        <category>
            <catname>Hotel</catname>
        </category>
        <category>
            <catname>Resort</catname>
        </category>
        <category>
            <catname>Golf & Spa</catname>
        </category>
    </hotel> 
    <hotel>
        <name>Hyatt</name>
        <category>
            <catname>Resort</catname>
        </category>
        <category>
            <catname>Golf & Spa</catname>
        </category>
    </hotel> 
</hotel>

но я бы хотел получить что-то вроде этого: (пример 2)

<hotels>
    <hotel>
        <name>Hilton Resort</name>
        <categories>  
            <catname>Hotel</catname>
            <catname>Resort</catname>
            <catname>Golf & Spa</catname>
        </categories>
    </hotel> 
    <hotel>
        <name>Hyatt</name>
        <categories>  
            <catname>Hotel</catname>
            <catname>Golf & Spa</catname>
        </categories>
    </hotel> 
</hotel>

Вот мой текущий код, который создает XML, как в примере 1:

        ...
        ...
        SqlDataAdapter hotelDA = new SqlDataAdapter(SQLHotels, SQLConn);
        SqlDataAdapter catDA = new SqlDataAdapter(SQLCats, SQLConn);

        DataSet ds = new DataSet("Hotels");

        hotelDA.Fill(ds, "Hotel");
        catDA.Fill(ds, "Category");

        DataRelation SleepRel = ds.Relations.Add("Hotel",
                 ds.Tables["Sleep"].Columns["Id"],
                 ds.Tables["Category"].Columns["AccID"]);
        SleepRel.Nested = true;
        SQLConn.Close();
        return ds;

SQLHotels - оператор SQL SELECT, который выбирает все отели
SQLCats - оператор SQL SELECT, который выбирает все категории
Id - идентификатор отеля
AccId - идентификатор отеля в таблице Категория (внешний ключ)

Мои вопросы:
1) Это действительно имеет значение? Одна структура лучше другой?
2) Можно ли установить связь между двумя таблицами в DataSet, чтобы получить вывод, как во втором (желательном) примере XML.

Ответы [ 3 ]

3 голосов
/ 01 апреля 2011

Одна структура лучше другой?

Лучше для чего? Формат DataSet очень хорош, если вы хотите иметь возможность считывать данные обратно в DataSet, поэтому, по крайней мере, по этому стандарту он превосходит тот, который вы предлагаете.

Вообще говоря, когда вы обрабатываете документ XML, вы будете искать в нем элементы, с которыми вы хотите работать, используя XPath или Linq. Сравните:

var categories = hotelElement.SelectNodes("category");
var categories = hotelXElement.Elements("category");

с:

var categories = hotelElement.SelectNodes("categories/category");
var categories = hotelXElement.Elements("categories").Element("category");

Что дает вам наличие промежуточных categories элементов? XML выглядит немного лучше в редакторе. Как правило, это не является неоспоримым преимуществом, особенно если это делает XML немного сложнее в обработке.

Можно ли установить связь между двумя таблицами в DataSet, чтобы получить вывод, как во втором (желательном) примере XML.

Нет. Формат сериализации DataSet очень жестко определен. Он поддерживает несколько параметров (вложение, включая схему, диаграммы), но формат не меняется (если вы не сохраняете в виде диаграмм, но если вы это сделаете, то как XML выглядит очень низко в вашем списке потребностей) ).

Вы можете использовать XSLT, чтобы довольно легко изменить формат. Добавьте это к преобразованию идентичности :

<xsl:template match="hotel">
   <xsl:apply-templates select="*[name() != 'category']"/>
   <xsl:if test="category">
      <categories>
         <xsl:apply-templates select="category"/>
      </categories>
   </xsl:if>
</xsl:template>
0 голосов
/ 07 апреля 2011

Вы можете написать sql, который будет производить желаемую модель в формате xml непосредственно из базы данных, например ...

SELECT HotelName,
       (select CategoryName from HotelCategories 
       where CategoryHotelName=HotelName
       for xml path('Category')) as Categories 
FROM Hotels 
for xml path('Hotels')

Конечно, в зависимости от вашей структуры БД ...

0 голосов
/ 01 апреля 2011

1) Это действительно имеет значение? Одна структура лучше другой?

Да, если вы добавили идентификатор категории в вывод категрии, то легко определить, какой идентификатор идет с каким именем

<category>
    <catId>1<cateId>
    <catname>Hotel</catname>
</category>
<category>
    <catId>2<cateId>
    <catname>Resort</catname>
</category>
<category>
    <catId>3<cateId>
    <catname>Golf & Spa</catname>
</category>

С другой стороны, трудно определить, какой идентификатор соответствует какому имени, потому что ассоциации являются позиционными.

<categories>
    <catId>1<cateId>
    <catname>Hotel</catname>
    <catId>2<cateId>
    <catname>Resort</catname>
    <catId>3<cateId>
    <catname>Golf & Spa</catname>
</categories>

2) Можно ли установить связь между двумя таблицами в DataSet, чтобы я получал выходные данные, как во втором (желательном) примере XML.

Существует ряд подходов, которые вы используете для этого ( linq to набор данных , XSLT и т. Д.), Но я не могу придумать прямой выход из рук.

...