使用嵌套元素将DataSet转换为XML

时间:2011-04-01 16:09:35

标签: c# xml web-services dataset nested

我正在编写一个应该将DataSet转换为XML的WebService。我的DataSet实际上是带有类别的酒店列表。每个酒店可以属于一个或多个类别。 我跟着HERE的一个例子,除了我没有得到我想要的结果外,它运作良好。

这就是我得到的:(示例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 - 酒店ID
AccId - 表格类别(外键)中的酒店ID

我的问题:
1)它真的重要吗?一个结构比另一个更好吗? 2)是否可以在DataSet中的两个表之间建立关系,因此我得到的输出就像它在第二个(所需的)XML示例中一样。

3 个答案:

答案 0 :(得分:3)

  

一个结构比另一个好吗?

更好的是什么? DataSet的格式非常好,如果您希望能够将数据读回DataSet,那么按照该标准,至少,它优于您提议的那个。< / p>

一般来说,当您处理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的序列化格式非常严格。它支持几个选项(嵌套,包括模式,diffgrams),但格式不会改变(除非您将其保存为diffgrams,但如果这样做,那么XML在您的需求列表中的外观非常低)。

但是,您可以使用XSLT轻松更改格式。将其添加到identity transform

<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>

答案 1 :(得分:0)

  

1)它真的重要吗?一个结构比另一个更好吗?

是的,如果您将类别ID添加到cateogry输出中,那么很容易说明Id与哪个名称相关

<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>

另一方面,这很难说明哪个Id与哪个名称相关,因为这些关联是位置的。

<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 dataset,XSLT等),但我无法想到一个直接的方法。

答案 2 :(得分:0)

您可以编写一个直接从数据库生成所需模型的sql,格式为xml格式,如...

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

当然取决于您的数据库布局......