spyne generating invalid schema - lxml

I am trying to use spyne from master branch as the released versions are not compatible with python3 and I have models defined like these:
class currency(ComplexModel):
data = XmlData(Decimal)
class mntCurrency(currency):
code = XmlAttribute(String)
class CreditLmt(ComplexModel):
curr = mntCurrency
I have plugged these models into a simple HelloWorld Service which returns CreditLmt in response. But when I try to run my soap server, spyne complains with the following:
lxml.etree.XMLSchemaParseError: Element
'{http://www.w3.org/2001/XMLSchema}extension': The content is not
valid. Expected is (annotation?, ((group | all | choice | sequence)?,
((attribute | attributeGroup)*, anyAttribute?)))., line 16
Which is correct because spyne generates the following xsd:
<xs:complexType name="mntCurrency">
<xs:complexContent>
<xs:extension base="tns:currency">
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="code" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
<xs:sequence>
<xs:element name="test" type="xs:token" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
I am using XmlData because I want to have reponse such that it looks like this:
<tns:currency code="826">10.0</tns:currency>
So how do I define my models?

An example for generating this element:
<tns:currency code="826">10.0</tns:currency>
... is as follows:
from spyne import *
from spyne.util.xml import get_object_as_xml
from lxml import etree
class Currency(ComplexModel):
value = XmlData(Decimal)
code = XmlAttribute(Integer32(values=[826, 234, 555]))
class SomeObject(ComplexModel):
handle = Unicode
currency = Currency
obj = SomeObject(handle="aaaa", currency=Currency(value=D('123.45'), code=555))
elt = get_object_as_xml(obj)
print(etree.tostring(elt, pretty_print=True))
As for the error, it is coming directly from libxml. It is essentially saying that the Xml Schema standard doesn't allow lone XmlData entries in a ComplexModel subclass. If you think this is an error, you must complain to the Xml Schema working group.

Related

XPATH assertion in xsd to check value of an attribute of first and last element of a complex type

I have the following xsd model and I need to have assertions to check on the type of first and last element of kPartsList : last part must be castOffPartPoint and first part must be castOnPartSeg;
I am using Python Package xmlSchema to validate the xml document
<?xml version="1.1" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace = "http://www.ludd21.com/kPartModel"
xmlns = "http://www.ludd21.com/kPartModel"
elementFormDefault="qualified"
vc:minVersion = "1.1"
xpathDefaultNamespace="##targetNamespace"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
>
<xs:element name="kPartModel">
<xs:complexType>
<xs:sequence>
<xs:element ref="kPartsPiece" minOccurs="1" maxOccurs = "unbounded"/>
</xs:sequence>
<xs:attribute name="modelName" type="xs:NCName" use = "required"/>
<xs:attribute name= "otherattribute" type="xs:string" default = ""/>
</xs:complexType>
<!--piecename must be unique within kpModel-->
<xs:unique name= "kPartModel">
<xs:selector xpath="*"/>
<xs:field xpath= "#pieceName"/>
</xs:unique>
</xs:element>
<xs:element name="kPartsPiece">
<xs:complexType>
<xs:sequence>
<xs:element ref= "kPartsList"/>
</xs:sequence>
<xs:attribute name="pieceName" type="xs:NCName"/>
<!-- #partNumber is unique across kPartsList -->
<xs:unique id = "unique-partNumber" name= "unique-partNumber">
<xs:selector xpath="*/*"/>
<xs:field xpath= "#partNumber"/>
</xs:unique>
</xs:element>
</xs:complexType>
<xs:element name = "kPartsList" >
<xs:complexType>
<xs:sequence>
<xs:choice minOccurs= "0" maxOccurs = "unbounded">
<xs:element ref = "castOnPartSeg" />
<xs:element ref = "joinPart"/>
<xs:element ref = "castOffPartPoint"/>
</xs:choice>
</xs:sequence>
<!-- last part must be castOff -->
<xs:assert id = "test-end-castOff" test = "(kPartsList[last()]/#type = 'castOffPartPoint') or (kPartsList[last()]/#type = 'castOffPartSeg')"/>
<!-- first part must be castOn-->
<xs:assert id = "test-first-castOn" test = "if (/#partNumber= '0') then #type = 'castOnPartSeg' else false()"/>
</xs:complexType>
</xs:element>
<xs:element name="castOffPartPoint">
<xs:complexType>
<xs:sequence>
<xs:element ref ="basePoint"/>
</xs:sequence>
<xs:attribute name ="nextsnum" type = "kpRefsList" use = "required"/>
<xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
</xs:complexType>
</xs:element>
<xs:element name="castOnPartSeg">
<xs:complexType>
<xs:sequence>
<xs:element ref ="baseSeg"/>
</xs:sequence>
<xs:attribute name = "nextsnum" type = "kpRefsList" use = "required"/>
<xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
</xs:complexType>
</xs:element>
<xs:element name="joinPart">
<xs:complexType>
<xs:sequence>
<xs:element ref ="baseSeg"/>
</xs:sequence>
<xs:attribute name ="nextsnum" type = "kpRefsList" use = "required"/>
<xs:attribute name ="previousnum" type = "kpRefsList" use = "required"/>
<xs:attribute name = "partNumber" type = "xs:nonNegativeInteger" use = "required"/>
</xs:complexType>
</xs:element>
<xs:simpleType name = "kpRefsList">
<xs:list itemType= "xs:nonNegativeInteger"/>
</xs:simpleType>
<xs:element name = "basePoint">
<xs:complexType>
<xs:attribute name= "start" type = "point" use = "required"/>
</xs:complexType>
</xs:element>
<xs:element name = "baseSeg">
<xs:complexType>
<xs:attribute name= "start" type = "point" use = "required"/>
<xs:attribute name= "end" type = "point" use = "required"/>
<!--startY = endY!-->
<xs:assert id = "test_base_horizontal" test = "/#start[2] = /#end[2]"/>
</xs:complexType>
</xs:element>
<xs:simpleType name= "point">
<xs:restriction>
<xs:simpleType>
<xs:list itemType = "decimal5digits"/>
</xs:simpleType>
<xs:length value = "2"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name ="decimal5digits">
<xs:restriction base = "xs:decimal">
<xs:fractionDigits value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
both assertions above always return false.
It should return true for this xml
<ns0:kPartModel xmlns:ns0="http://www.ludd21.com/kPartModel" modelName="manysingulars" otherattribute="">
<ns0:kPartsPiece pieceName="pieceknit_layer1">
<ns0:kPartsList>
<ns0:castOnPartSeg nextsnum="1" partNumber="0">
<ns0:baseSeg start="9.73143 0.00000" end="17.73188 0.00000" />
</ns0:castOnPartSeg>
<ns0:joinPart nextsnum="2" previousnum="0 2" partNumber="1" >
<ns0:baseSeg start="9.88173 -11.82912" end="25.27907 -11.82912" />
</ns0:joinPart>
<ns0:castOffPartPoint partNumber="2">
<ns0:basePoint start="21.83789 -8.02031"/>
</ns0:castOffPartPoint>
</ns0:kPartsList>
</ns0:kPartsPiece>
</ns0:kPartModel>

WCF Desrialization of date with offset

I am facing an issue where wcf response contains datetime stamp as
1978-05-20T11:12:00+2:00
I want to retrieve the response as the same like 1978-05-20T11:12:00.
Please note, this offset (+02:00 in the above example) value might change for different response. So value might be
1978-05-20T11:12:00+2:00
1978-05-20T11:12:00+5:00
1978-05-20T11:12:00+6:00
Here is what I did to fix this...
update the wsdl file from
<xs:element name="start" type="xs:date"/>
to
<xs:element name="start" type="xs:string"/>
and generated the proxy.. now the returned value with using this proxy was like 1978-05-20T11:12:00+2:00 in start field. they I used string function to extract just the desired part.
Alternatively, proxy file can be updated from
[XmlAttribute( type = "Date", ElementName = "start" )]
public DateTime start {
..
}
to
[XmlAttribute( type = "string", ElementName = "start" )]
public string start {
...
}

Dataset deserialization to object issue - vb .net

Hi everyone i'm having some trouble deserializing a dataset (with parent table) to the correspondent object.
Every table have is array object inside his parent object for deserialization, every array have default {}, but if parent table have no rows the inner object is set to nothing, not empty array... how may i correct this issue?!?
Thanks a lot to everyone.
VB .Net code:
Public Function DeserializeDataSetToObj(ByRef DataSetIn As DataSet, ByVal t As Type) As Object
Dim obj As Object = Nothing
Dim stream As MemoryStream = New MemoryStream()
Using writer As XmlWriter = XmlWriter.Create(stream)
DataSetIn.WriteXml(writer)
End Using
stream.Seek(0, SeekOrigin.Begin)
Using reader As XmlReader = XmlReader.Create(stream)
Try
Dim xmlSer As System.Xml.Serialization.XmlSerializer = New System.Xml.Serialization.XmlSerializer(t)
obj = xmlSer.Deserialize(reader)
Catch ex As Exception
End Try
End Using
Return obj
End Function
Objects Class
<Serializable(), XmlRoot("MainDataset"), XmlType("MainDataset")>
Public Class MainDataset
<XmlElement("Header1")>
Public Property Header1() as HeaderType
<XmlElement("Header2")>
Public Property Header2() as HeaderType
End Class
<Serializable()>
Public Class HeaderType
<XmlElement("Rows")>
Public Property Rows() as RowType
End Class
<Serializable()>
Public Class RowType
<XmlElement("ColumnA")>
Public Property ColumnA as String
<XmlElement("ColumnB")>
Public Property ColumnB as String
<XmlElement("ColumnC")>
Public Property ColumnC as String
End Class
XSD:
<?xml version="1.0" standalone="yes"?>
<xs:schema id="MainDataset" xmlns="" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element msdata:UseCurrentLocale="true" name="MainDataset">
<xs:complexType>
<xs:sequence>
<xs:element name="Header1">
<xs:complexType>
<xs:sequence>
<xs:element name="Rows">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="ColumnA" type="xs:string"/>
<xs:element minOccurs="0" name="ColumnB" type="xs:string"/>
<xs:element minOccurs="0" name="ColumnC" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Header2">
<xs:complexType>
<xs:sequence>
<xs:element name="Rows">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="ColumnA" type="xs:string"/>
<xs:element minOccurs="0" name="ColumnB" type="xs:string"/>
<xs:element minOccurs="0" name="ColumnC" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Problem solved... if i use list instead array i receive an empty list not a nothing object.
Thanks to everyone

Mapping JAXBelement in Mule Data mapper

I have a generated SOAP response from a wsdl for one Web Service. This is how one of the elements looks like in the wsld definition:
<xs:element minOccurs="0" name="Name" nillable="true" type="xs:string"/>
In the POJO, it looks like this :
#XmlElementRef(name = "Name", namespace = "http://schemas.datacontract.org/2004/07/Web.WebServices", type = JAXBElement.class, required = false)
protected JAXBElement<String> name;
When trying to set the value, in the Data Mapper, I see the following:
The problem is that I am not allowed to just drag and drop the "name" value.
How should I map the name value from the JSON on the left to the name value?
You will have to drag input.name to the value field of name name/value.
Script view should look something like:
output.value = input.name;

Search for multiple values in an xml column

Environment: SQL Server 2012. Primary and secondary (value) index is built on xml column.
Say I have a table Message with xml column WordIndex. I also have a table Word which has WordId and WordText. Xml for Message.WordIndex has the following schema:
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com">
<xs:element name="wi">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="w">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="p" type="xs:unsignedByte" />
</xs:sequence>
<xs:attribute name="wid" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
and some data to go with it:
<wi xmlns="http://www.example.com">
<w wid="1">
<p>28</p>
<p>72</p>
<p>125</p>
</w>
<w wid="4">
<p>89</p>
</w>
<w wid="5">
<p>11</p>
</w>
</wi>
I need to search for multiple values in my xml column WordIndex either using OR or AND. What I'm doing is fairly rudimentary, since I'm a n00b in XQuery (taken from debug output, hence real values):
with xmlnamespaces(default 'http://www.example.com')
select
m.Subject,
m.MessageId,
m.WordIndex.query('
let $dummy := 0
return
<word_list>
{
for $w in /wi/w
where $w/#wid=64
return <word wid="64" pos="{data($w/p)}"/>
}
{
for $w in /wi/w
where $w/#wid=70
return <word wid="70" pos="{data($w/p)}"/>
}
{
for $w in /wi/w
where $w/#wid=63
return <word wid="63" pos="{data($w/p)}"/>
}
</word_list>
') as WordPosition
from
Message as m
-- more joins go here ...
where
-- more conditions go here ...
and m.WordIndex.exist('/wi/w[#wid=64]') = 1
and m.WordIndex.exist('/wi/w[#wid=70]') = 1
and m.WordIndex.exist('/wi/w[#wid=63]') = 1
How can this be optimized?
Not sure I understand what your expected results are, but you could make this a bit more generic and data-driven (eg using sql:column or sql:variable). Try something like this:
declare #wids table ( wid INT PRIMARY KEY )
insert into #wids ( wid )
values ( 64 ), ( 70 )
;with xmlnamespaces(default 'http://www.example.com')
select
m.Subject,
m.MessageId,
m.WordIndex.query('
return
<word_list>
{
for $w in /wi/w
where $w/#wid = sql:column("w.wid")
return <word wid="{$w/#wid}" pos="{data($w/p)}"/>
}
</word_list>
') as WordPosition
from
Message as m
cross apply #wids w
where m.WordIndex.exist('wi/w[#wid=sql:column("w.wid")]') = 1