Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C#] Dataset > XML geeft problemen bij NULL values

Pagina: 1
Acties:

  • StarLite
  • Registratie: Januari 2000
  • Laatst online: 18-11 15:24

StarLite

'ON ERROR RESUME NEXT

Topicstarter
Ik zit met het volgende probleem:
Ik krijg van een webservice (via SOAP) een XML+XSD aangeleverd die ik in een dataset gooi en die aan een datagrid knoop, dit werkt allemaal prima.

Nu wil ik een (of meerdere) row(s) uit de datagrid terugsturen (via SOAP) naar de webservice. Dit doe ik dmv de volgende code:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
           DataSet changedDsRows = new DataSet();
            XmlDocument schemaDoc = new XmlDocument();
            XmlDocument dataDoc = new XmlDocument();
            XmlDocument dataSetDoc = new XmlDocument();
            XmlElement root;
            XmlNode schemaNode;
            XmlNode dataNode;

            changedDsRows = ds.GetChanges();
            if (changedDsRows != null)
            {
                schemaDoc.Load(new StringReader(changedDsRows.GetXmlSchema()));
                dataDoc.Load(new StringReader(changedDsRows.GetXml()));

                dataSetDoc.LoadXml("<DataSet></DataSet>");
                root = dataSetDoc.DocumentElement;
                root.SetAttribute("xmlns", "");

                schemaNode = dataSetDoc.ImportNode(schemaDoc.DocumentElement, true);
                dataNode = dataSetDoc.ImportNode(dataDoc.DocumentElement, true);
                root.AppendChild(schemaNode);
                root.AppendChild(dataNode);
                objTable = dataSetDoc.DocumentElement;

                try 
                { 
                    svc_admin.insertrow(tabel, objTable); 
                }
                catch (SoapException f) 
                { 
                    lbl_status.Text = f.Message.ToString() + ": " + f.Detail.InnerText.ToString(); 
                }
                ds.AcceptChanges();
            }

Dit werkt goed zolang ik alle velden in de row invoer.
Maar op het moment dat er 1 of meerdere velden leeg zijn, krijg ik een SOAP exception dat hij een veld mist.
Het probleem zit hem in .GetXML(): als die een NULL value tegenkomt in de dataset laat hij het hele element weg.
Ik krijg als output dan:
XML:
1
2
3
4
5
6
<Data>
  <Item>
    <UserCd>test</UserCd>
    <UserName>Test User</UserName>
  </Item>
</Data>


Terwijl SOAP het volgende vereist:
XML:
1
2
3
4
5
6
7
8
<Data>
  <Item>
    <UserCd>test</UserCd>
    <UserName>Test User</UserName>
    <UserPrinter/>
    <rowid/>
  </Item>
</Data>


Ik heb flink gegoogled en er zijn heel veel mensen met hetzelfde probleem, maar er is geen fatsoenlijke oplossing in mijn geval. Ze gaan er allemaal vanuit dat je weet welke kolommen er in de dataset zitten. Dat weet ik niet, de dataset wordt opgebouwd aan de hand van de XSD data die ik van mijn webservice krijg.
Ik kan de input van de dataset niet bepalen, die krijg ik van de webservice, die levert lege elementen aan die vervolgens als NULL in de dataset terecht komen.
GetXML() kan geen lege elementen uitpoepen, hij laat ze altijd weg.

Ik zit met een paar mogelijke oplossingen:
* Zelf een dataset naar XML parser schrijven, die null values wél als leeg element toevoegt aan mijn XML. (tijdrovend, lastig en waarschijnlijk overbodig)
* Een manier vinden om via bestaande functies mijn XML goed outgeput te krijgen. Ik las iets over de WriteXML() functie die aan de hand van een XSD XML output, maar die krijg ik ook niet zo ver dat hij lege elementen aanmaakt...
* Zorgen dat de dataset geen NULL values kan bevatten, wat lastig is omdat ik vantevoren niet weet welke datatypes er in de dataset/datagrid komen.

Wat zie ik over het hoofd, het moet toch mogelijk zijn om lege elementen in mijn XML te krijgen adhv een dataset?

Mijn XSD (voor een voorbeeld tabel):
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<xs:schema id="Data" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="Data" msdata:IsDataSet="true" msdata:Locale="en-US">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Item">
<xs:complexType>
<xs:sequence>
<xs:element name="UserCd" type="xs:string" minOccurs="0" />
<xs:element name="UserName" type="xs:string" minOccurs="0" />
<xs:element name="UserPrinter" type="xs:string" minOccurs="0" />
<xs:element name="rowid" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>

tyrips, tywreps, tiewreps, tiereps, tie raps, ripties, taiwraps, kabelbindbandjes » Tie Wraps
\o/


Verwijderd

Uit de XSD is op te maken dat het element met de naam UserPrinter niet hoeft te bestaan. Het lijkt mij dan normaal dat het element weg wordt gelaten als deze niet gevuld wordt.

Waar treedt de fout exact op? Is dit bij de cliënt of op de webserver? Als dit op de webserver is lijkt het erop dat de XSD niet overeenkomt. Dan zouden de elementen het attribute nillable="true" moeten bevatten met minOccurs="1". Dan wordt er verplicht het element mee te versturen, maar dit mag leeg zijn (nillable).

  • StarLite
  • Registratie: Januari 2000
  • Laatst online: 18-11 15:24

StarLite

'ON ERROR RESUME NEXT

Topicstarter
Ik krijg als foutmelding:
code:
1
Error in SOAP parameter: Column "UserCd" missing from "tth" row (10914)0d99e72630acf161:-7fc0f67f:116c8a9f3bb:-7fff#fa

Op het moment dat ik de webservice aanroep met een "onvolledige" xml (waar in dit geval het UserCd veld niet is gevult)
De melding komt dus via SOAP terug van de webservice.


Als ik
C#:
1
SchemaDoc.Load(new StringReader(changedDsRows.GetXmlSchema()));


vervang door:
C#:
1
schemaDoc.Load(new StringReader("<?xml version=\"1.0\" encoding=\"utf-16\"?><xs:schema id=\"Data\" xmlns=\"\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">  <xs:element name=\"Data\" msdata:IsDataSet=\"true\" msdata:Locale=\"en-US\">    <xs:complexType>      <xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\">        <xs:element name=\"Item\">          <xs:complexType>            <xs:sequence>              <xs:element name=\"UserCd\" type=\"xs:string\" minOccurs=\"1\" nillable=\"true\" />              <xs:element name=\"UserName\" type=\"xs:string\" minOccurs=\"1\" nillable=\"true\" />              <xs:element name=\"UserPrinter\" type=\"xs:string\" minOccurs=\"1\" nillable=\"true\" />              <xs:element name=\"rowid\" type=\"xs:string\" minOccurs=\"1\" nillable=\"true\" />            </xs:sequence>          </xs:complexType>        </xs:element>      </xs:choice>    </xs:complexType>  </xs:element></xs:schema>"));


Krijg ik als output:
XML:
1
2
3
4
5
6
7
8
9
<xs:schema id="Data" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="Data" msdata:IsDataSet="true" msdata:Locale="en-US">
<xs:complexType><xs:choice minOccurs="0" maxOccurs="unbounded"><xs:element name="Item"><xs:complexType><xs:sequence><xs:element name="UserCd" type="xs:string" minOccurs="1" nillable="true" /><xs:element name="UserName" type="xs:string" minOccurs="1" nillable="true" /><xs:element name="UserPrinter" type="xs:string" minOccurs="1" nillable="true" /><xs:element name="rowid" type="xs:string" minOccurs="1" nillable="true" /></xs:sequence></xs:complexType></xs:element></xs:choice></xs:complexType></xs:element></xs:schema>
<Data>
<Item>
<UserName>Test</UserName>
<UserPrinter>Test user</UserPrinter>
</Item>
</Data>

En de SOAP error blijft :(

[ Voor 82% gewijzigd door StarLite op 11-12-2007 15:27 ]

tyrips, tywreps, tiewreps, tiereps, tie raps, ripties, taiwraps, kabelbindbandjes » Tie Wraps
\o/


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Volgens mij is de combinatie minOccurs="0" en nillable="true" wat jij zoekt.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Verwijderd

Het wordt mij toch iets te mysterieus of te ingewikkeld ;)

Weet je zeker dat de betreffende DataRow de DataColumn 'UserPrinter' bevat?
Als dit zo is en de kolom 'UserPrinter' bevat een null waarde moet .NET dit parsen naar een leeg maar wel bestaand Xml element. (Zojuist getest in een stukje eigen code, wel op een iets andere wijze).

Ik wens je iig succes met het oplossen van het probleem, misschien komt er nog een XMLguru langs ;)

PS. Het choice element in het Schema is overbodig.

[ Voor 5% gewijzigd door Verwijderd op 11-12-2007 16:00 ]


  • StarLite
  • Registratie: Januari 2000
  • Laatst online: 18-11 15:24

StarLite

'ON ERROR RESUME NEXT

Topicstarter
De kolom user printer bestaat wel, hij staat ook gewoon in de datagrid, zoals het hoort. Alleen is het veld meestal leeg.

Wat ook lekker vaag is:
ik heb de volgende code:
C#:
1
2
ds.ReadXmlSchema(new XmlTextReader("c:\\xsd.xml"));
ds.WriteXmlSchema("c:\\test.xml");


Alleen komen xsd.xml en test.xml NIET overeen, terwijl deze 2 regels zo onder elkaar in mijn programma staan, zonder code ertussen 8)7
Als ik expres een typfout maak ik de xsd waardoor hij niet meer geldig is, krijg ik een error op runtime, dus hij leest & parsed de xsd wel gewoon.

[ Voor 32% gewijzigd door StarLite op 11-12-2007 16:56 ]

tyrips, tywreps, tiewreps, tiereps, tie raps, ripties, taiwraps, kabelbindbandjes » Tie Wraps
\o/


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Heb je nou al geprobeerd om de velden die null moeten kunnen te zijn in je schema op minOccurs="0" en nillable="true" te zetten dan?
Op zich hoeft het niet veel te zeggen dat de bestanden niet hetzelfde zijn natuurlijk, als ze maar wel hetzelfde betekenen. Kan me zo voorstellen dat bij het inlezen de hele zut in een DOM geplaatst wordt en bij het wegschrijven die DOM gebruikt wordt zodat de output wel altijd hetzelfde is maar niet gelijk hoeft te zijn aan de input.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack

Pagina: 1