3

DataSetデータから XML を作成したいのですが、データベースからまたはでデータを受信して​​いますIList<Booking>。現在DataSet、このコードで XML を作成するために使用しています。

string result = String.Empty;

using (StringWriter sw = new StringWriter())
 {
   ds.WriteXml(sw);
   result = sw.ToString();
 }

そして、私の XML はこの形式です。

<Booking> 
    <ID>32</ID> 
    <BookingNumber>12120001</BLNumber> 
    <ReferenceNo>ABCED11212280007</ReferenceNo> 
    <Name>Customer Name1</Name> 
    <Address>Customer Address</Address>
</Booking>

<Booking> 
    <ID>33</ID> 
    <BookingNumber>12120002</BLNumber> 
    <ReferenceNo>ABCED11212280008</ReferenceNo> 
    <Name>Customer Name2</Name> 
    <Address>Customer Address2</Address>
</Booking>



<BookingDetail> 
   <ID>206</ID> 
   <BookingID>32</BookingID> 
   <OrderItem>Item1</OrderItem> 
</BookingDetail>

<BookingDetail> 
   <ID>207</ID> 
   <BookingID>32</BookingID> 
   <OrderItem>Item2</OrderItem> 
</BookingDetail>

<BookingDetail> 
   <ID>208</ID> 
   <BookingID>33</BookingID> 
   <OrderItem>Item1</OrderItem> 
</BookingDetail>

<BookingDetail> 
   <ID>209</ID> 
   <BookingID>33</BookingID> 
   <OrderItem>Item2</OrderItem> 
</BookingDetail>

<BookingDetail> 
   <ID>210</ID> 
   <BookingID>33</BookingID> 
   <OrderItem>Item3</OrderItem> 
</BookingDetail>

しかし、この形式の XML が必要です。

<CompleteBooking>
 <Booking> 
    <ID>32</ID> 
    <BookingNumber>12120001</BLNumber> 
    <ReferenceNo>ABCED11212280007</ReferenceNo> 
    <Name>Customer Name1</Name> 
    <Address>Customer Address</Address>
 </Booking>

 <BookingDetail> 
   <ID>206</ID> 
   <BookingID>32</BookingID> 
   <OrderItem>Item1</OrderItem> 
 </BookingDetail>

 <BookingDetail> 
   <ID>207</ID> 
   <BookingID>32</BookingID> 
   <OrderItem>Item2</OrderItem> 
 </BookingDetail>

</CompleteBooking>

<CompleteBooking>
 <Booking> 
    <ID>33</ID> 
    <BookingNumber>12120002</BLNumber> 
    <ReferenceNo>ABCED11212280008</ReferenceNo> 
    <Name>Customer Name2</Name> 
    <Address>Customer Address2</Address>
 </Booking>

 <BookingDetail> 
   <ID>208</ID> 
   <BookingID>33</BookingID> 
   <OrderItem>Item1</OrderItem> 
 </BookingDetail>

 <BookingDetail> 
   <ID>209</ID> 
   <BookingID>33</BookingID> 
   <OrderItem>Item2</OrderItem> 
 </BookingDetail>

 <BookingDetail> 
   <ID>210</ID> 
   <BookingID>33</BookingID> 
   <OrderItem>Item3</OrderItem> 
 </BookingDetail>

</CompleteBooking>

このタイプの XML の作成を手伝ってくれる人はいますか?

4

6 に答える 6

5

System.Xml.Serializationを使用して、予約のオブジェクトを作成します。

public class XMLEntities
{   
  [XmlRoot(ElementName = "CompleteBooking")]
  public class CompleteBooking
  {
    [XmlElement(ElementName = "Booking")]
    public Booking Bookings { get; set; }

    [XmlElement(ElementName = "BookingDetail")]
    public List<BookingDetail> BookingDetail { get; set; }
  }

  public class Booking
  {
    [XmlElement("ID")]
    public int ID { get; set; }

    [XmlElement("BookingNumber")]
    public int BookingNumber { get; set; }

    [XmlElement("ReferenceNumber")]
    public string ReferenceNumber { get; set; }

    [XmlElement("Name")]
    public string Name { get; set; }

    [XmlElement("Address")]
    public string Address { get; set; }
  }

  public class BookingDetail
  {
    [XmlElement("ID")]
    public int ID { get; set; }

    [XmlElement("BookingID")]
    public int BookingID { get; set; }

    [XmlElement("OrderItem")]
    public string OrderItem { get; set; }
  }
}

ここで、シリアライザーオブジェクト(実際にオブジェクトを文字列にシリアル化するために使用されます)の場合:

 public class XMLEntitiesSerializer
 {
   public string Serialize(XMLEntities.CompleteBooking completeBooking)
   {
     var serializedXml = string.Empty;

     var serializer = new XmlSerializer(typeof (XMLEntities.CompleteBooking));
     var stringWriter = new System.IO.StringWriter();

     try
     {
       serializer.Serialize(stringWriter, completeBooking);
       serializedXml = stringWriter.ToString();
     }
     catch(Exception ex)
     {
       //Log the stuff
     }
     finally
     {
       stringWriter.Close();
     }

     return serializedXml;
   }
 }

これで、正しく定義されたオブジェクトを作成し、ある種の関数でシリアル化するだけです。たとえば、コンソールアプリケーションのメインメソッドでは次のようになります。

public static void Main(string[] args)
{
  //Create new booking objects
  var booking1 = new XMLEntities.Booking()
                  {
                    ID = 32,
                    BookingNumber = 1212001,
                    ReferenceNumber = "ABCED11212280007",
                    Name = "Customer Name1",
                    Address = "Customer Address"
                  };
  var booking2 = new XMLEntities.Booking()
                   {
                     ID = 33,
                     BookingNumber = 12120002,
                     ReferenceNumber = "ABCED11212280008",
                     Name = "Customer Name2",
                     Address = "Customer Address2"
                   };

  //Create the booking details objects

  var booking1Detail1 = new XMLEntities.BookingDetail()
                         {
                           ID = 206,
                           BookingID = 32,
                           OrderItem = "Item1"
                         };
  var booking1Detail2 = new XMLEntities.BookingDetail()
                          {
                            ID = 207,
                            BookingID = 32,
                            OrderItem = "Item2"
                          };

  var booking2Detail1 = new XMLEntities.BookingDetail()
                          {
                            ID = 208,
                            BookingID = 33,
                            OrderItem = "Item1"
                          };
  var booking2Detail2 = new XMLEntities.BookingDetail()
                          {
                            ID = 209,
                            BookingID = 32,
                            OrderItem = "Item2"
                          };
  var booking2Detail3 = new XMLEntities.BookingDetail()
                          {
                            ID = 210,
                            BookingID = 32,
                            OrderItem = "Item3"
                          };

  //Smash them together so we can serialize as one

  var completeBooking1 = new XMLEntities.CompleteBooking()
                          {
                            Bookings = booking1,
                            BookingDetail = new List<XMLEntities.BookingDetail>()
                                              {
                                                booking1Detail1,
                                                booking1Detail2
                                              }
                          };
  var completeBooking2 = new XMLEntities.CompleteBooking()
                           {
                             Bookings = booking2,
                             BookingDetail = new List<XMLEntities.BookingDetail>()
                                               {
                                                 booking2Detail1,
                                                 booking2Detail2,
                                                 booking2Detail3
                                               }
                           };

  //Serialize the data for each of the booking objects

  var serializedXML = new XMLEntitiesSerializer();
  var xml = string.Empty;

  var booking1XmlString = serializedXML.Serialize(completeBooking1);
  var booking2XmlString = serializedXML.Serialize(completeBooking2);

  Console.ReadLine();
}

明らかに、これをリファクタリングされた関数で使用できます(これにより作業が楽になります)が、これにより、求めている一般的な出力が得られます。

于 2013-02-22T16:28:33.253 に答える
3

これを行う方法の 1 つを次に示します。

        DataTable Booking = new DataTable();
        Booking.Columns.AddRange(new DataColumn[]{ new DataColumn("ID"), new DataColumn("BookingNumber"), new DataColumn("ReferenceNo"), new DataColumn("Name"), new DataColumn("Address") });

        DataTable BookingDetail = new DataTable();
        BookingDetail.Columns.AddRange(new DataColumn[] { new DataColumn("ID"), new DataColumn("BookingID"), new DataColumn("OrderItem") });

        Booking.Rows.Add(32, 12120001, "ABCED11212280007", "Customer Name1", "Customer Address");
        BookingDetail.Rows.Add(206, 32, "Item1");
        BookingDetail.Rows.Add(207, 32, "Item2");

        Booking.Rows.Add(33, 12120002, "ABCED11212280008", "Customer Name2", "Customer Address2");
        BookingDetail.Rows.Add(208, 33, "Item1");
        BookingDetail.Rows.Add(209, 33, "Item2");
        BookingDetail.Rows.Add(210, 33, "Item3");

        XElement root = new XElement("Root");

        // For each row from Booking add one CompleteBooking element
        foreach(DataRow BookingRow in Booking.Rows.Cast<DataRow>())
        {
            XElement xeCompleteBooking = new XElement("CompleteBooking");

            XElement xeBooking = new XElement("Booking");
            int BookingID = Convert.ToInt32(BookingRow["ID"]);

            IEnumerable<string> columnNames_Booking = Booking.Columns.Cast<DataColumn>().Select(col => col.ColumnName);
            // Add element under Booking element for every column of table
            foreach (string colName in columnNames_Booking)
                xeBooking.Add(new XElement(colName, BookingRow[colName]));

            xeCompleteBooking.Add(xeBooking);

            IEnumerable<string> columnNames_BookingDetail = BookingDetail.Columns.Cast<DataColumn>().Select(col => col.ColumnName);

            // For Booking.ID find all BookingDetail rows according to BookingDetail.BookingID
            IEnumerable<DataRow> details = BookingDetail.Rows.Cast<DataRow>().Where(BookingDetailRow => Convert.ToInt32(BookingDetailRow["BookingID"]) == BookingID);
            foreach (DataRow BookingDetailRow in details)
            {
                XElement xeBookingDetail = new XElement("BookingDetail");

                // Add element under BookingDetail element for every column of table
                foreach (string colName in columnNames_BookingDetail)
                    xeBookingDetail.Add(new XElement(colName, BookingDetailRow[colName]));

                xeCompleteBooking.Add(xeBookingDetail);
            }

            root.Add(xeCompleteBooking);
        }

        string xml = root.ToString();

LINQ to XML を使用します。列名を読み取って適切な名前の XML 要素を作成するため、テーブルにいくつかの列を追加または削除しても、これが壊れてはなりません。固定列名を持つべき列はID( Booking) とBookingID( BookingDetail) のみです。これらはリンクに使用されるためです。 2 つのテーブル。

于 2013-02-21T08:06:04.803 に答える
2

データに次のクラスがあるとします。

class Booking
{
    public int ID { get; set;}
    public int BookingNumber { get; set;}
    public string ReferenceNo { get; set;}
    public string Name { get; set;}
    public string Address { get; set;}
}

class BookingDetails
{
    public int ID { get; set;}
    public int BookingId { get; set;}
    public string OrderItem { get; set;}
}

そして次のテストデータ:

    static private IList<Booking> _bookings = new List<Booking>() {
        new Booking() { ID = 32, BookingNumber = 12120001, ReferenceNo = "ABCED11212280007", Name = "Customer Name1", Address = "Customer Address" },
        new Booking() { ID = 33, BookingNumber = 12120002, ReferenceNo = "ABCED11212280008", Name = "Customer Name2", Address = "Customer Address2" }
    };

    static private IList<BookingDetails> _details = new List<BookingDetails>() {
        new BookingDetails() { ID = 206, BookingId = 32, OrderItem = "Item1" },
        new BookingDetails() { ID = 207, BookingId = 32, OrderItem = "Item2" },
        new BookingDetails() { ID = 208, BookingId = 33, OrderItem = "Item1" },
        new BookingDetails() { ID = 209, BookingId = 33, OrderItem = "Item2" },
        new BookingDetails() { ID = 210, BookingId = 33, OrderItem = "Item3" }
    };

次の Linq to XML クエリを使用して、特定の形式で出力 XML を簡単に取得できます。

var bookings = _bookings.Join(_details, b => b.ID, d => d.BookingId, (b, d) => new { b, d })
                        .GroupBy(g => g.b, g => g.d)
                        .Select(g => new XElement("CompleteBooking",
                                        new XElement("Booking", 
                                            new XElement("ID", g.Key.ID),
                                            new XElement("BookingNumber", g.Key.BookingNumber),
                                            new XElement("ReferenceNo", g.Key.ReferenceNo),
                                            new XElement("Name", g.Key.Name),
                                            new XElement("Address", g.Key.Address)),
                                        g.Select(d => new XElement("BookingDetail",
                                                            new XElement("ID", d.ID),
                                                            new XElement("BookingID", d.BookingId),
                                                            new XElement("OrderItem", d.OrderItem))).ToArray())).ToArray();

XElement オブジェクトの配列が得られます。xml 文字列を取得するには、次のString.Join<XElement>メソッドを使用します。

var xmlString = String.Join<XElement>(Environment.NewLine, bookings);

ただし、少し異なる XML スキーマをお勧めします。

<Bookings>
  <Booking>
    <ID>32</ID>
    <BookingNumber>12120001</BookingNumber>
    <ReferenceNo>ABCED11212280007</ReferenceNo>
    <Name>Customer Name1</Name>
    <Address>Customer Address</Address>
    <Details>
      <Detail>
        <ID>206</ID>
        <OrderItem>Item1</OrderItem>
      </Detail>
      <Detail>
        <ID>207</ID>
        <OrderItem>Item2</OrderItem>
      </Detail>
    </Details>
  </Booking>
  <Booking>
    <ID>33</ID>
    <BookingNumber>12120002</BookingNumber>
    <ReferenceNo>ABCED11212280008</ReferenceNo>
    <Name>Customer Name2</Name>
    <Address>Customer Address2</Address>
    <Details>
      <Detail>
        <ID>208</ID>
        <OrderItem>Item1</OrderItem>
      </Detail>
      <Detail>
        <ID>209</ID>
        <OrderItem>Item2</OrderItem>
      </Detail>
      <Detail>
        <ID>210</ID>
        <OrderItem>Item3</OrderItem>
      </Detail>
    </Details>
  </Booking>
</Bookings>

そのような形式のデータには冗長性がありません。それを取得するには、次のクエリを使用します。

var bookings = _bookings.Join(_details, b => b.ID, d => d.BookingId, (b, d) => new { b, d })
                        .GroupBy(g => g.b, g => g.d)
                        .Select(g => new XElement("Booking", 
                                        new XElement("ID", g.Key.ID),
                                        new XElement("BookingNumber", g.Key.BookingNumber),
                                        new XElement("ReferenceNo", g.Key.ReferenceNo),
                                        new XElement("Name", g.Key.Name),
                                        new XElement("Address", g.Key.Address),
                                        new XElement("Details",
                                            g.Select(d => new XElement("Detail",
                                                              new XElement("ID", d.ID),
                                                              new XElement("OrderItem", d.OrderItem))).ToArray()))).ToArray();

var data = new XDocument(new XElement("Bookings", bookings));
于 2013-02-23T20:53:21.953 に答える
2

データ オブジェクトで XmlSerializer クラスを使用できませんか? それとも私は質問を誤解していますか?

オブジェクトの構造が見えなければ、「もし私があなたの立場だったら...」と言う以外にできることはほとんどありません。

必要なのは、1 つがリスト (BookingDetail) である場合に、同じタグの下に「Booking」と「BookingDetail」の 2 種類のオブジェクトがあるという点で、「非標準」XML です。

この形式にする必要がある場合、これについて私が行う方法は手動のシリアル化です。

public String Serialize(CompleteBooking [] cbs) {
    String FinalXML = "<CompleteBookings>";
    foreach(CompleteBooking cb in cbs) {
        FinalXML += cb.ToXML();
    }
    FinalXML += "</CompleteBookings>";
}

そしてデータオブジェクト:

public class CompleteBooking {
    public Booking Booking;
    public BookingDetail [] BookingDetails

    public String ToXML() {
        String RVal = "<CompleteBooking>" + this.Booking.ToXML();
        foreach(BookingDetail bd in BookingDetails) {
            RVal += bd.ToXML();
        }
        RVal += "</CompleteBooking>"


    }
}

public class Booking {
    // Fields Here
    public String ToXML() {
        return "<Booking>" + [Fields] + "</Booking>";
    }
}

public class BookingDetail {
    // Fields Here
    public String ToXML() {
        return "<BookingDetail>" + [Fields] + "</BookingDetail>";
    }
}
于 2013-02-15T06:52:33.600 に答える
1

@Umair Noorさん、あなたの質問に対する私のコメントに従うのが遅れて申し訳ありません。

あなたは .NET を扱っているので、必要DataSetな XML を .NET から取得する最も簡単な方法を次に示します。関連するオンライン リファレンスを参照してください。

  1. 表示する XML 出力を表す XML ドキュメントを作成します。 質問ではすでにこれを行っています<\BLNumber>が、1)終了タグをタグに置き換え<\BookingNumber>、2) サンプル内の複数のルート要素に関する @ByteBlast のポイントに対処する必要があります。

    あなたが望むXMLの例を最小限に調整することで、私がすぐに最終的に得たものは次のとおりです。

    <Bookings> <!-- fix for multiple root elements -->
      <CompleteBooking>
        <Booking>
          <ID>32</ID>
          <BookingNumber>12120001</BookingNumber> <!-- fixed BLNumber closing tag -->
          <ReferenceNo>ABCED11212280007</ReferenceNo>
          <Name>Customer Name1</Name>
          <Address>Customer Address</Address>
        </Booking>
    
        <BookingDetail>
          <ID>206</ID>
          <BookingID>32</BookingID>
          <OrderItem>Item1</OrderItem>
        </BookingDetail>
    
        <BookingDetail>
          <ID>207</ID>
          <BookingID>32</BookingID>
          <OrderItem>Item2</OrderItem>
        </BookingDetail>
    
      </CompleteBooking>
    
      <CompleteBooking>
        <Booking>
          <ID>33</ID>
          <BookingNumber>12120002</BookingNumber> <!-- fixed BLNumber closing tag -->
          <ReferenceNo>ABCED11212280008</ReferenceNo>
          <Name>Customer Name2</Name>
          <Address>Customer Address2</Address>
        </Booking>
    
        <BookingDetail>
          <ID>208</ID>
          <BookingID>33</BookingID>
          <OrderItem>Item1</OrderItem>
        </BookingDetail>
    
        <BookingDetail>
          <ID>209</ID>
          <BookingID>33</BookingID>
          <OrderItem>Item2</OrderItem>
        </BookingDetail>
    
        <BookingDetail>
          <ID>210</ID>
          <BookingID>33</BookingID>
          <OrderItem>Item3</OrderItem>
        </BookingDetail>
    
      </CompleteBooking>
    </Bookings> <!-- fix for multiple root elements -->
    
  2. xsd.exeコマンドライン ツールを使用して、代表的な XML ファイルから XML スキーマ定義 (XSD) ファイルを生成します。

    または、XML ファイルを読み取るための数行のコードを記述し、 を使用XmlReadMode.InferSchemaしてそのスキーマを生成します。生成されたスキーマを XSD ファイルに書き込みます。たとえば、WPF スクラッチ アプリのボタン イベント ハンドラーにすばやく挿入したものを次に示します。

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        // BEGIN: the bottom-line logic
        var ds = new DataSet();
    
        var sr = new StreamReader("Bookings.xml"); // file into which I put your sample, desired XML
        ds.ReadXml(sr, XmlReadMode.InferSchema); // XmlReadMode.InferSchema - key
        sr.Close();
    
        ds.WriteXmlSchema("Bookings.xsd"); // file into which I got the resulting schema
        // END: the bottom-line logic
    }
    

    どちらの方法も十分に迅速です。

  3. XSDファイルを使用...

    <?xml version="1.0" standalone="yes"?>
    <xs:schema id="Bookings" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
      <xs:element name="Bookings" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
        <xs:complexType>
          <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="CompleteBooking">
              <xs:complexType>
                <xs:sequence>
                  <xs:element name="Booking" minOccurs="0" maxOccurs="unbounded">
                    <xs:complexType>
                      <xs:sequence>
                        <xs:element name="ID" type="xs:string" minOccurs="0" />
                        <xs:element name="BookingNumber" type="xs:string" minOccurs="0" />
                        <xs:element name="ReferenceNo" type="xs:string" minOccurs="0" />
                        <xs:element name="Name" type="xs:string" minOccurs="0" />
                        <xs:element name="Address" type="xs:string" minOccurs="0" />
                      </xs:sequence>
                    </xs:complexType>
                  </xs:element>
                  <xs:element name="BookingDetail" minOccurs="0" maxOccurs="unbounded">
                    <xs:complexType>
                      <xs:sequence>
                        <xs:element name="ID" type="xs:string" minOccurs="0" />
                        <xs:element name="BookingID" type="xs:string" minOccurs="0" />
                        <xs:element name="OrderItem" type="xs:string" minOccurs="0" />
                      </xs:sequence>
                    </xs:complexType>
                  </xs:element>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:choice>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    ...型付きDataSet(例:BookingsまたはBookingsDataSet) を定義する - 使用している可能性が高い汎用目的DataSetではありません。

    手順 3 の XSD ファイルでxsd.exeのオプションを使用するか、Visual Studio でプロジェクトに新しい項目を追加してから、手順 3 で派生したスキーマをそのファイルに貼り付けることができます。/d[ataset]DataSet.xsd

    同じ - どちらにしても十分速い。

  4. 正確な結果が得られるまで、必要に応じて繰り返します。

正式な参考資料として、MSDN にはADO.NET における XML の概要があり、ここで説明した内容の多くが説明されています。


于 2013-02-25T11:23:47.460 に答える
1

LINQ to XML を使用してカスタム構造を作成できます。ネストされた XElement コンストラクターを使用します。たとえば、この構造の XML を作成する方法とc# を使用して XML を動的に構築する方法を参照してください。

于 2013-02-15T06:45:38.850 に答える