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
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>
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 {
...
}
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
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;
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