StrataFrame Forum

Business Objects and XML import/export

http://forum.strataframe.net/Topic7591.aspx

By Robin J Giltner - 3/19/2007

I am tasked with providing a means of exporting and importing records from one client to another.  I started out using the BusinessObject.CurrentDataTable.WriteXML(Filename), and using the subsequent DataSet.ReadXML(filename), and copying the data with a BusinessObject.CopyDataFrom(DataSet.Tables(0), AppedDatatoTableFromCompleteTable) method and this worked fine.   I looked through the sample XML datasource project and it appears to be using the method I had and was working well.

Then I read the post about decrpyting XML and using the Microfour XML namespace methods to generate XML files from datasets.  With this the schema was placed in the file along with the versioning and built in encryption, so I decided to start working on switching to this method.

Using the MicroFour.StrataFrame.XML.XMLBasics.WriteXMLFile(Dataset, filename) this seems to generate the XML file fine.

'-- Write DataSet to XML

Dim loDS As New DataSet

loDS.Tables.Add(MyBusinessObject.CurrentDataTable)

'-- Write the DataSet to XML to the SaveFileDialog's Filename

MicroFour.StrataFrame.Xml.XmlBasics.WriteXmlFile(loDS, loSaveFileDialog.FileName, False)

My problem comes with trying to read this back in using the ReadXMLFile method.

'-- Instantiate a new DS

Dim loDS As New DataSet

'-- Fill the Dataset from the XML file

loDS.ReadXmlSchema(loOpenFileDialog.FileName)

'-- Declare some locals for Listing DataColumns from XML schema

Dim loCol As DataColumn

Dim laCols As New System.Collections.Generic.List(Of DataColumn)

'-- Iterate through Table(0) and build List of DataColumns

For Each loCol In loDS.Tables(0).Columns

laCols.Add(loCol)

Next

'-- Read the XML file into the DataSet

loDS = MicroFour.StrataFrame.Xml.XmlBasics.OpenXmlFile("1.0", loDS.Tables(0).TableName, loOpenFileDialog.FileName, laCols, False)

When it gets to the OpnXMLFile method it checks for the version of the XML and always returns -1, and writes the XMLVersion table to the xml file with no data in the XML datatable(0) where the data was.

Before xml file

<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="U_NSN" msdata:CaseSensitive="False" msdata:Locale="en-US">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="U_NSN_PK" msdataBigGrinataType="System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
                <xs:element name="U_NSN_Nomenclature" type="xs:string" minOccurs="0" />
                <xs:element name="U_NSN_Price" type="xs:decimal" minOccurs="0" />
                <xs:element name="U_NSN_Weight" type="xs:double" minOccurs="0" />
                <xs:element name="U_NSN_Volume" type="xs:double" minOccurs="0" />
                <xs:element name="U_NSN_UOMFK" msdataBigGrinataType="System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
                <xs:element name="U_NSN_UserID" type="xs:string" minOccurs="0" />
                <xs:element name="U_NSN_Public" type="xs:boolean" minOccurs="0" />
                <xs:element name="U_NSN_cncDateTime" type="xs:dateTime" minOccurs="0" />
                <xs:element name="U_NSN_FSCFK" msdataBigGrinataType="System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
                <xs:element name="U_NSN_CountryCodeFK" msdataBigGrinataType="System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" minOccurs="0" />
                <xs:element name="U_NSN_PartialName" type="xs:string" minOccurs="0" />
                <xs:element name="U_NSN_FullName" type="xs:string" minOccurs="0" />
                <xs:element name="U_NSN_CON_DATETIME" type="xs:dateTime" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <U_NSN>
    <U_NSN_PK>e2579dbf-a73a-4681-bbb2-43f2c2b9eed1</U_NSN_PK>
    <U_NSN_Nomenclature>Air Conditioning equipment from iceland.  I think its just a bag of ice.</U_NSN_Nomenclature>
    <U_NSN_Price>0.8500</U_NSN_Price>
    <U_NSN_Weight>8</U_NSN_Weight>
    <U_NSN_Volume>1.252</U_NSN_Volume>
    <U_NSN_UOMFK>eaa6e172-5bc5-4e54-ac49-292618f6cf7e</U_NSN_UOMFK>
    <U_NSN_UserID />
    <U_NSN_Public>false</U_NSN_Public>
    <U_NSN_cncDateTime>1800-01-01T00:00:00-06:00</U_NSN_cncDateTime>
    <U_NSN_FSCFK>982d5ae6-b301-4785-83dc-39064590f594</U_NSN_FSCFK>
    <U_NSN_CountryCodeFK>fd49f597-e560-4f15-b037-746c49357137</U_NSN_CountryCodeFK>
    <U_NSN_PartialName>1121445</U_NSN_PartialName>
    <U_NSN_FullName>4120IS1145445</U_NSN_FullName>
    <U_NSN_CON_DATETIME>2007-03-08T12:56:49.693-06:00</U_NSN_CON_DATETIME>
  </U_NSN>
</NewDataSet>

After the code runs to read the file

<?xml version="1.0" standalone="yes"?>
<XmlStructure>
  <xs:schema id="XmlStructure" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="XmlStructure" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="XmlVersionInfo">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="xml_Version" type="xs:string" default="" minOccurs="0" />
                <xs:element name="xml_ValidationKey" type="xs:string" default="" minOccurs="0" />
                <xs:element name="xml_Comment" type="xs:string" default="" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
          <xs:element name="U_NSN">
            <xs:complexType>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <XmlVersionInfo>
    <xml_Version>1.0</xml_Version>
    <xml_ValidationKey />
    <xml_Comment>Created on Monday, March 19, 2007 at 12:47:05 PM
Version upgraded from 0.0.0.0 to 1.0 on Monday, March 19, 2007 at 12:47:05 PM</xml_Comment>
  </XmlVersionInfo>
  <U_NSN />
</XmlStructure>

What am I missing here?

Thanks,

Robin Giltner

 

Heh, the colon-capital 'D' gets changed to a BigGrin. Heh.

By Trent L. Taylor - 3/19/2007

When you use the XML namespace to create and write the XML files, it adds a versioning table within the data set so that you can actually upgrade the structure of an XML file...just like the DDT.  This allows existing XML files with a particular structure to have new columns added or existing ones removed.  So we add a versioning table which occupies the zero index position.

This is the table you are pulling out.  You need to pull out your table which would be something like this:

loDS.Tables(1)

If you pull the zero index you will always get the versioning table.

By Robin J Giltner - 3/19/2007

Ok.  I took all references to the Datatable by INdex out, and just used the DataTable name ("U_NSN").

I still seem to be having a problem on reading the XML file.  If the version information isn't present when it tries to read in the XML file, it generates the version block, and its schema, but also removes the schema information for my U_NSN data table that was there, and removes the data for the U_NSN data table.

If I take the version information from the resulting XML file, and the data and schema from the original XML file and piece them together, so that is has schema info for both the Version block, and the U_NSN data table, as well as the data for the Version block and U_NSN block, it works great.

Do I need to be generating the version information when I generate the XML file containing the U_NSN data/schema?

Thanks,

Robin Giltner

By Trent L. Taylor - 3/19/2007

You are making it too complicated. BigGrin  The XML tools in the framework deal in data sets, not data tables.  The reason for this is the auto-managed versioning table that resides in the data set.  So take the BO out of the forumla for a second.  If you have a data table that is in the data set that should belong to the BO then let the open of the XML.

''' <summary>
    ''' Writes the XML
    ''' </summary>
    ''' <param name="MyBO"></param>
    ''' <remarks></remarks>
    Private Sub WriteToXML(ByVal MyBO As MyBusinessObjectType)
        '-- Establish Locals
        Dim loDS As New System.Data.DataSet()

        '-- Add the data table to the data set.  Use the CurrentView since it will respect
        '   any filters and sorts.  Also this will prevent any object reference associations.
        loDS.Tables.Add(MyBO.CurrentView.ToTable("MyTableName"))

        '-- Write the XML file (Add a True to the end for encryption)
        MicroFour.StrataFrame.Xml.XmlBasics.WriteXmlFile(loDS, "c:\temp\MyXML.xml")
    End Sub

    ''' <summary>
    ''' Opens the XML file and moves the data in the XML file into the BO
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub OpenAndLoadBO()
        MyBO.CopyDataFrom(OpenXMLTableAndRetrieveDataTable(), StrataFrame.Business.BusinessCloneDataType.ClearAndFillFromCompleteTable)
    End Sub

    ''' <summary>
    ''' Reads the data from the XML file and returns the data table
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function OpenXMLTableAndRetrieveDataTable() As System.Data.DataTable
        '-- Establish Locals
        Dim loDS As System.Data.DataSet

        '-- Open the XML file and read it into a data set (Add a True at the end for decryption)
        loDS = MicroFour.StrataFrame.Xml.XmlBasics.OpenXmlFile("1.0", "MyTableName", "c:\temp\MyXML.xml", CreateMyDataStructure())

        '-- Pull out the only table that you need
        Return loDS.Tables("MyTableName")
    End Function

    ''' <summary>
    ''' Creates the expected data structure
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CreateMyDataStructure() As System.Collections.Generic.List(Of System.Data.DataColumn)
        '-- Establish Locals
        Dim loReturn As New System.Collections.Generic.List(Of System.Data.DataColumn)

        '-- Create the data structure to be returned
        loReturn.Add(MicroFour.StrataFrame.Xml.XmlBasics.CreateXmlDataColumn("MyField", GetType(Integer), 0))
        loReturn.Add(MicroFour.StrataFrame.Xml.XmlBasics.CreateXmlDataColumn("MyName", GetType(String), ""))

        Return loReturn
    End Function

The above code should give you a basic understand of how to use the XMLBasics class as it relates to opening and writing XML files.  This class exists to make it easy to encrypt, decrypt, and update the data structures of an XML file.  If you do not have any of these needs that this class may be overkill for what you are trying to accomplish.

By Robin J Giltner - 3/20/2007

Awesome, thank you thank you.  The ability to add version information for future structure changes and to let the user decide wether or not to encrypt was the reason for trying this.  And it works now, well of course it does, I copied the code you gave me and ran with it :-)

Not sure what the problem was, might have been they way I was building my ColumnStructure list, but anyway. Thanks a ton as usual.

Robin

By Trent L. Taylor - 3/20/2007

Glad to help Smile