Topic
  • 1 reply
  • Latest Post - ‏2012-03-10T15:43:20Z by SystemAdmin
MisterMan
MisterMan
1 Post

Pinned topic Element Content is invalid according to the DTD\schema

‏2012-02-22T13:24:08Z |
Sorry if I am being too wordy. I need assistance and i need it fast. This is my first post here, I never knew I could add attachment. Perhaps

Hello all. I am having serious issues with a project that I am handling. The client makes request to the server, and the server obliges by sending the date (in XML of course). No problem here at all. The client (written in VB) is supposed to make changes (adding more data in fact) and send it back to the server. Here is where the problem is.

This is the strategy I used. The VB client creates ADO records and adds the extracted data from the XML for the purpose of adding and editting. For new records, new nodes are created. Here is where I am having issues: Element Content is invalid according to the DTD\schema. The code compares the ADO records with entries in the XML tree. If they are found, it simply updates the values. For those that are NOT found, it creates nodes and then updates the nodes with values form the ADO records. This is where the issue lies.

Here is the relevant part of the code where the problem is:

Private Sub SaveOtherInfo(DOMDocument As MSXML2.DOMDocument, Nodestring As String, _
TagName As String, ADORecordset As adodb.Recordset)

Dim loRows As IXMLDOMNodeList, loRow As IXMLDOMNode, NewNode As IXMLDOMNode, _
loFields As IXMLDOMNodeList, loField As IXMLDOMNode, _
Found As Boolean, oTemplate As IXMLDOMNode ', Okay As Boolean
Set loRows = DOMDocument.selectNodes(Nodestring)

' The above is the set of records (the table)
ADORecordset.MoveFirst
' Start at the top
While Not ADORecordset.EOF
Found = False
'Okay = False
For Each loRow In loRows
Set loFields = loRow.childNodes
For Each loField In loFields
If LCase(loField.nodeName) = "code" Then
' This is the field we are interested in
If loField.Text = ADORecordset.fields(loField.nodeName).Value Then
Found = True
End If
Exit For
End If
Next

' Up to here, it is either found or not
If Not Found Then

'FOR ANYBODY WHO WANTS TO HELP, THIS IS WHERE I THINK THE PROBLEM IS. PLEASE LET'S PAY CLOSE ATTENTION
If oTemplate Is Nothing Then
' It has not been created. We purposely put this code here so that
' the code will be created only when it is neccessary
Dim ParentNode As IXMLDOMNode
Set ParentNode = DOMDocument.selectSingleNode(Nodestring)
Set oTemplate = DOMDocument.createElement(TagName)
ParentNode.appendChild oTemplate
' Create object variable that will be used to loop thru
' the name in the ADORecordset
Dim EachField As adodb.Field
' Go thru the field name to create the nodes
For Each EachField In ADORecordset.fields
Set loField = DOMDocument.createElement(EachField.Name)
'loField.Text = ADORecordset.fields.Item(EachField).Value
loField.Text = ADORecordset.fields(loField.nodeName).Value
oTemplate.appendChild loField
Next
End If

' Loop thru all the fields and create them
' That is why we created the template that will be used
Else
For Each loField In loFields
loField.Text = ADORecordset.fields(loField.nodeName).Value
Next
End If
ADORecordset.MoveNext
loRows.nextNode
If ADORecordset.EOF Then
Exit For
End If
Next
Wend
End Sub

  • <PCs xmlns="x-schema:#pcs">
- <PC>
387
<usercode type="string" size="10">3659384993</usercode>
<year type="string" size="4">1992</year>
<title type="string" size="2147483647">xNational Youth Service Corps (NYSC)</title>
<weight type="string" size="1">5</weight>
<deleteit type="boolean" size="1">0</deleteit>
- <PC xmlns=""> THIS SHOULD NOT BE THIS INDENTED. IT MAKES IT TO BE A CHILD NODE OF THE FIRST <PC>
737 NOTICE THAT THE ATTRIBUTES SUCH AS ARE MISSING. HOW DO I DO THIS?
<usercode />
<year>2000</year>
<title>MCSE</title>
<weight>5</weight>
<deleteit />
</PC>
</PC>
</PCs>

I will apreciate assistance from any quaters. Thanks in anticipation of your kind assistance.
Updated on 2012-03-10T15:43:20Z at 2012-03-10T15:43:20Z by SystemAdmin
  • SystemAdmin
    SystemAdmin
    1138 Posts

    Re: Element Content is invalid according to the DTD\schema

    ‏2012-03-10T15:43:20Z  
    I have just taken some time to have a look at your code. I find it a bit confusing with some unnecessary twists etc, no doubt because that is not my code and that I spend not good enough time looking at it.

    Two main things you've to pay attention:
    [1] Make sure you understand you're profiting from the namespace being default, hence, you have the luxury not to worry qualifying names explicitly. But, when you create an element, you cannot be of that luck, you still need to feed the namespace uri;
    [2] Pay attention to where new elements being inserted into: that is, the parent node should be located properly before appending child...
    [3] If you think conditioning oTemplate being nothing is useful, you've to make sure after its use, you set it to nothing explicitly before looping on again.
    >Set ParentNode = DOMDocument.selectSingleNode(Nodestring)
    No, that is too much a hazard and depends on pure luck that that is the right parent node. In general, that is the wrong parent node. Instead do this.
    
    Set ParentNode = loRow.parentNode
    


    >Set oTemplate = DOMDocument.createElement(TagName)
    Here you depend on the input parameter TagName. But, it seems you want to insert PC which is the local name of the loRow which in turns coming from loRows and then Nodestring. If that's the case, I would suggest you have to spare that input argument (to rule out chances of a mismatch) and use directly the loRow. Like this.

    Set oTemplate = DOMDocument.createElement(loRow.NodeName)

    But that's still not quite right. That would create a tag PC in null namespace. In fact, it is not the other PC tags. Hence, it should be written like this.
    
    Set oTemplate = DOMDocument.createNode(1, loRow.NodeName, loRow.NamespaceURI)
    

    Like this, you don't need to hard code the namespace (x-schema:#pcs). Here is what I meant the code relying on some luck if you happened to input nodestring without prefix. That hooks the usefulness of the sub to default namespace case - that's very undesirable. In any case, make the story short...

    >Set loField = DOMDocument.createElement(EachField.Name)
    Here again, the same problem.
    
    Set loField = DOMDocument.createNode(1, EachField.Name, loRow.NamespaceURI)
    

    I think the above fixes the main hurdle, the rest... just be careful in putting the right field names, etc etc... I can't deal with them with the limited info displayed.