Sending Complex Objects, Attachments with ksoap2-Android - serialization

I'm using ksoap2-Android on an Android project to upload a file. It's not working.
First of all, my wsdl looks like this:
<xsd:element name="Op1RequestType">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="date" type="xsd:dateTime"/>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="imgFile"
type="tns:Attachment"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
And "tns:Attachment" is defined like this:
<xsd:complexType name="Attachment">
<xsd:sequence>
<xsd:element name="file" type="xsd:base64Binary"/>
<xsd:element name="filename" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
I'm creating a SoapSerializationEnvelope and adding in the property with name date and the value as the string representation of the current date. This works successfully, even if I don't add a file (note the minOccurs="0"). However, when I try to add a file, it fails horribly:
First, I make a representative of the Attachment type by creating a SoapObject which has the properties file and filename, of types byte[].class and String.class respectively.
Then I add these objects to a generic Vector (to represent the multiplicity of the imgFile item) and attach the Vector as a property to the envelope. This creates a SOAP message successfully, and the response from the server raises an exception (because it's an error message, instead of a proper response, because somehow my input isn't good...):
WARN/System.err(438): SoapFault - faultcode: 'soapenv:Server'
faultstring:'org.apache.axis2.databinding.ADBException: Unexpected subelement imgFile'
faultactor: 'null' detail: org.kxml2.kdom.Node#4676b8a0
Okay, so what am I doing wrong? Is there a way to see the request SOAP envelope that I am sending?

I can see the request SOAP envelope by calling getRequest() on the SoapSerializationEnvelope. This allowed me to see that the vector object actually places each (file, filename) pair into an <item></item> tag, which broke the format. I now am inserting multiple items in succession as the wsdl demands.

Related

XQuery Error when reading attribute from parentnode with *typed* XML (value() requires a singleton)

I have a simple XML:
DECLARE #x1 xml = '<r>
<o a="1">
<o a="2">
</o>
</o>
</r>';
And select the following:
SELECT r.o.value('(../#a)[1]','varchar(20)') FROM #x1.nodes('/r//o') r(o);
Everything is nice:
NULL
1
When I use typed XML:
CREATE XML SCHEMA COLLECTION [dbo].test AS '
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="r">
<xsd:complexType>
<xsd:complexContent>
<xsd:restriction base="xsd:anyType">
<xsd:sequence>
<xsd:element name="o" type="o" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="o">
<xsd:complexContent>
<xsd:restriction base="xsd:anyType">
<xsd:sequence>
<xsd:element name="o" type="o" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="a" type="xsd:string" />
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>'
GO
DECLARE #x2 xml(dbo.test) = '<r>
<o a="1">
<o a="2">
</o>
</o>
</r>';
SELECT r.o.value('(../#a)[1]','varchar(20)') FROM #x2.nodes('/r//o') r(o);
I got the Error:
XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
Why does the untyped XML works and the typed XML not?
It looks as though you well understand that this is not the usual problem of having to convince the parser that there is only one thing being passed into value(). This problem is specific to typed XML, as you have observed.
Using google I found this ancient blogpost with the promising text
rt is part of the XQuery 1.0/XPath 2.0 data model.
Most people get by that. The real fun starts when you do examples using untyped XML and XPath expressions with the text() node test. text() works just fine when using untyped XML, but fails against typed XML with simple content
It talks about the SQL Books Online and the SQL Server 2005 XML Best Practices paper, which I think is this book here. I haven't looked for a more up-to-date reference. But using what I found there I have been able to fix your problem: Simple replace
SELECT r.o.value('(../#a)[1]','varchar(20)') FROM #x2.nodes('/r//o') r(o);
with
SELECT r.o.value('fn:string(../#a)[1]','varchar(20)') FROM #x2.nodes('/r//o') r(o);
Basically, value() doesn't like being given values of a typed-xml-type, but wants strings. So we give it a string.

Invalid XML element location. (SQL-XSD)

I just started learning XML today. I was trying to create a 'sample' XSD and populate it but.. I made up my data and it looks fine, but I can't make this schema work..
CREATE XML SCHEMA COLLECTION GenreTestSchema
AS
<?xml version = "1.0" encoding = "UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--create group for GENRELIST-->
<xsd:group name="GENRELISTGROUP">
<xsd:element name="GENRELIST">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="GENRE" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="REFERENCE" minOccurs="0" maxOccurs="100" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:group>
</xsd:schema>
Now If I remove this element
<xsd:element name="GENRELIST">
and all the code that goes with it so (element and complextype) then the schema works fine. I can't figure out what is wrong here and why it doesn't let me create this element?
Errorlog
Element <element> is not valid at location '/*:schema[1]/*:group[1]/*:element[1]'.
It talks about invalid location but I literally have no idea why?
Data sample
<GENRELIST xmlns="http://myGenres">
<GENRE GenreNo="1">
<GENRE>Fiction</GENRE>
<REFERENCE>Alien</REFERENCE>
</GENRE>
<GENRE GenreNo="2">
<GENRE>Tragedy</GENRE>
<REFERENCE>Titanic</REFERENCE>
</GENRE>
</GENRELIST>
The problem is that you're missing to take the namespace xmlns="http://myGenres" into account on the element GENRELIST.
So transform your anonymous complex type to a named type and use the namespace on it:
<?xml version = "1.0" encoding = "UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:gl="http://myGenres"
targetNamespace="http://myGenres"
elementFormDefault="qualified">
<xsd:complexType name="genrelist"> <!-- named type 'genrelist' -->
<xsd:sequence>
<xsd:element name="GENRE" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="REFERENCE" minOccurs="0" maxOccurs="100" />
</xsd:sequence>
</xsd:complexType>
<!--create group for GENRELIST-->
<xsd:element name="GENRELIST" type="gl:genrelist" /> <!-- applying the 'gl' namespace to named type 'genrelist' -->
</xsd:schema>
This way your XML will be validated.
For the purpose of targetNamespace look here and for
elementFormDefault look there.
I don't know why you're trying to create an xs:group (a "model group"). A model group is a reusable chunk of schema declarations that can be used in several places, handy when you have multiple elements with similar structure. It might sometimes make sense to have a group with only one reference to it, but it can't make sense to have a group with no references to it.
Now there's an additional (and related) problem). Typically when you start validating an instance document, the validator looks for a global element declaration whose name matches the root element of the instance. But you don't have a global element declaration in your schema; your declaration of GENRELIST isn't global because it is in a group.

SQLXMLBulkLoad Schema Validation Issue (Easy)

I have a huge XML file full of employees and information, and have a question.
Example of XML File:
<Employees>
<Employee>
<EmployeeID>blah</EmployeeID>
<FirstName>blah</FirstName>
<LastName>blah</LastName>
<MiddleName>blah</MiddleName>
.......... and on
</Employee>
........ and on
</Employees>
My schema, so far is like this:
<?xml version="1.0" encoding="utf-8"?>
<xsd:element name="Employees" sql:relation="The_Employees">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Employee">
<xsd:element name="EmployeeID" sql:field="EmpNo" type="xsd:integer"/>
<xsd:element name="FirstName" sql:field="FirstName">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:whiteSpace value="collapse"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
.......... and on
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
From my research, the root element is supposed to contain the relation with your table in the DB (for privacy sake, the name in this example is "The_Employees") So, I made that relation, and also made the sql:field for each column in the table because the column names are different than the XML Element tags in most cases. However, in what ways to do I relate each individual <Employee> tag to my table? Also, whilst validating the XML, it throws this error:
The content of 'Employee' must match (annotation?, (simpleType |
complexType)?, (unique | key | keyref)*)). A problem was found
starting at: element.
It seems like the validator is thinking that I am trying to split the content into two separate tables and therefore need to annotate that, but I am not. Any suggestions?
Just FYI: The end product here is going to be a VB.NET program which uses SQLXMLBulkLoad to load the data from the XML file into a fresh SQL Table.
Alright... the fix was simple and I am answering this so that someone in the future may refer to it. If you have a root element as well as each individual parent element under that root element and you are using BulkLoad, then you can set the root element to sql:is-constant = 1. This tells the schema that the root element exists, but to ignore it. Also, the above schema was ammended to:
<xsd:element name="Employees" sql:is-constant=1>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Employee" sql:relation="The_Employees">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="EmployeeID" sql:field="EmpNo" type="xsd:integer"/>
<xsd:element name="FirstName" sql:field="FirstName">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:whiteSpace value="collapse"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
.......... and on
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

Validate XML against a schema having any element

I have a schema say called BPMN20.xsd having an element called extensionElements.see sample below:
<xsd:element name="extensionElements" type="tExtensionElements" />
<xsd:complexType name="tExtensionElements">
<xsd:sequence>
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
Now the xml contains elements inside extensionElements, which conform to another schema say ufl.xsd. Example:
<extensionElements>
<ufl:java method="calculate"
class="com.companyx.orchestration.bpmn.ordermanagement.data.CalculateOrderAmount">
<ufl:arg type="com.companyx.orchestration.bpmn.ordermanagement.data.OrderLine"
var="item" />
</ufl:java>
</extensionElements>
Now i want to validate my XML against both the schemas. How to do this ?
If i just validate my xml against BPMN20.xsd it works (since content if extensionElements is defined as any. However i also want to validate the contents inside extensionElements against ufl.xsd
Please help...
Thanks,
Siddharth
Use processContents as lax in the schema where you defined the any element.
This will enforce the converter in finding the schema element for the passed xml.

any element in XML schema blocks XQuery

I have the following XML Schema:
CREATE XML SCHEMA COLLECTION test AS '
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="PointConf">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="GlobalFlags">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Order" type="OrderType"/>
<xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="OrderType">
<xsd:attribute name="value" type="xsd:int" />
</xsd:complexType>
</xsd:schema>
'
GO
Then I use it in this way:
DECLARE #xml xml(test)
SET #xml='<PointConf>
<GlobalFlags>
<Order value="1" />
</GlobalFlags>
</PointConf>'
SELECT #xml.value('(/PointConf/GlobalFlags/Order/#value)[1]','int')
SELECT gives me the following error:
XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type '(xs:int | xdt:anyAtomicType *) ?'
Without the xsd:any element in the schema the code above works without any errors. What am I doing wrong?
I got the select to work by using the statement
SELECT #xml.value('string(/PointConf[1]/GlobalFlags/Order[1]/#value)','int')
I understand the requirement for the [1] index on the Order node, as this can be a list, however I don't see why its required for the PointConf node.
The [1] needs to be used at the actual level where a list exists to restrict that list to a single return value
The string(...) turns the node set into a string (or empty string). I think this helps with the xsd:any although I'm not completely sure why - something to do with handling the possibility of the node Order being missing completely I think.
Update:
Investigating further:
SELECT #xml.value('string((/PointConf/GlobalFlags/Order/#value)[1])','int')
also works.
So its just the string function that's required to make it work in this instance.