I have a string field named "accountNumber" as part of an object used in a webservice. I need this field to have minOccurs="1" but WITHOUT nillable="true".
If I define that field as <XmlElement(IsNullable:=True)> then I get minOccurs="1" and nillable="true". If I define <XmlElement(IsNullable:=False)> then I don't get nillable="true", but I get minOccurs="0" instead.
So, how do I define my object to get this in my XSD:
<s:element minOccurs="1" maxOccurs="1" name="accountNumber" type="s:string" />
My class definition is very simple:
<Serializable()> _
<XmlType(Namespace:="http://mysite.org")> _
Public Class MyServiceWS
'some other definitions
<XmlElement(IsNullable:=True)> <VBFixedString(64)> Public accountNumber As String
End Class
Thank you for any help.
EDIT Oct 16, 2012: reverse engineering XSD
I reverse engineered XSD with the following fields:
<xs:element name="TEST1" minOccurs="1" maxOccurs="1" type="xs:string"/>
<xs:element name="TEST2" minOccurs="0" maxOccurs="1" type="xs:string"/>
<xs:element name="TEST3" minOccurs="1" maxOccurs="1" nillable="true" type="xs:string"/>
<xs:element name="TEST4" minOccurs="0" maxOccurs="1" nillable="false" type="xs:string"/>
I used the following command: xsd.exe MyClass.xsd /classes /language:vb /f
The following results were produced:
'''<remarks/>
Public TEST1 As String
'''<remarks/>
Public TEST2 As String
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute(IsNullable:=true)> _
Public TEST3 As String
'''<remarks/>
Public TEST4 As String
Judging from this result, it doesn't seem to be possible to do what I want to accomplish.
EDIT Oct 17, 2012: found a post with similar issue
For all those interested in this issue, I found a post with similar problem. There was no solution provided.
How to make a dotnet webservice set minOccurs=“1” on a string value
As far as I know, what I am asking is not possible to automate through .NET. I would have to alter the WSDL manually.
I have posted a detailed answer on another thread with the same problem: How to make a dotnet webservice set minOccurs=“1” on a string value.
However the short answer is no. It's not possible for string types.
String types have a default value of String.Empty, and minOccurs won't be set to 1 unless there is no default value (which is only possible using IsNullable = true for string).
Related
I am receiving a document in Biztalk, which contain some base64 encoded content inside an xml tag.
What I need, is to decode this content (which is a seperate XML document) and insert it into an in an envelope schema, to then be processed further.
The structure of the received document is like so:
<Polling xmlns="http://schemas.microsoft.com/Sql/2008/05/Polling/">
<PolledData>
<DataSet xmlns="http://schemas.datacontract.org/2004/07/System.Data">
<xs:schema id="NewDataSet" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element msdata:IsDataSet="true" name="NewDataSet">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="NewTable">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="ID" type="xs:string"/>
<xs:element minOccurs="0" name="hostUTC" type="xs:dateTime"/>
<xs:element minOccurs="0" name="msgType" type="xs:string"/>
<xs:element minOccurs="0" name="acknowledgment" type="xs:string"/>
<xs:element minOccurs="0" name="sendLog" type="xs:string"/>
<xs:element minOccurs="0" name="msgFormat" type="xs:string"/>
<xs:element minOccurs="0" name="msgbody" type="xs:base64Binary"/>
<xs:element minOccurs="0" name="fromID" type="xs:string"/>
<xs:element minOccurs="0" name="toID" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<NewTable>
<ID>123</ID>
<hostUTC>2018-11-08T14:53:24.11Z</hostUTC>
<msgType>INVOIC</msgType>
<msgFormat>Edifact</msgFormat>
<msgbody>base64encodedmessage...</msgbody>
<fromID>DKT:28504861</fromID>
<toID>KMDoioUBL</toID>
</NewTable>
</NewDataSet>
</diffgr:diffgram>
</DataSet>
</PolledData>
</Polling>
The base64 encoded content is located inside the tag.
I've already created the envelope schema, which has the following structure:
The message is received using a WCF-SQL adapter on a receive location. Currently no pipeline has been set up to process the message. In the 'Messages' tab of the adapter configuration it seems there is an option for base64 encoding, though I am not sure what this does or how it works exactly. When using the body setting here I get returned the above XML.
I'm not sure if this can be done without writing any code.
Reading this post on the subject, it seems that I need to write a custom pipeline component to handle the decoding. But first I would need to extract the content of the specific XML node.
I'm unsure how to approach this problem. I'd like to avoid using orchestrations if at all possible. Can this be done in standard Biztalk, or will I need to create custom functionality to handle this process?
Edit: XPath attempts
/Polling/PolledData[1]/*[namespace-uri()='http://schemas.datacontract.org/2004/07/System.Data' and local-name()='DataSet'][1]/*[namespace-uri()='urn:schemas-microsoft-com:xml-diffgram-v1' and local-name()='diffgram'][1]/*[namespace-uri()='' and local-name()='NewDataSet'][1]/*[namespace-uri()='' and local-name()='NewTable'][1]/*[namespace-uri()='' and local-name()='msgbody'][1]
/*[local-name()='Polling']/*[local-name()='PolledData']/*[local-name()='DataSet']/*[local-name()='diffgram']/*[local-name()='NewDataSet']/*[local-name()='NewTable']/*[local-name()='msgbody']
/Polling/PolledData/DataSet/diffgr:diffgram/NewDataSet/NewTable/msgbody
//*[msgbody]/text()
I have a situation where I am storing a complex object in Gemfire. For simplicity it is a customer object who has several attributes. We also store a List of email address objects (not just email strings), addresses, phone numbers, and references to "foreign systems" I need to determine the best way to query data.
First the Object Structure (pseudo xsd for simplicity)
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="customer">
<xs:complexType>
<xs:sequence>
<xs:element name="firstName" type="xs:string"/>
<xs:element name="lastName" type="xs:string"/>
...
<xs:element name="emailAddresses" type="emailAddressType" minOccurs="1"/> <!-- one or more -->
<xs:element name="foreignSystemIdentifiers" type="foreignSystemIdentifierType"/> <!-- zero or more -->
...
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="emailAddressType">
<xs:complexType>
<xs:element name="emailAddress" type="xs:string"/>
<xs:element name="addressType" type="xs:string"/>
...
</xs:complexType>
</xs:element>
<xs:element name="foreignSystemIdentifierType">
<xs:complexType>
<xs:element name="foreignSystemName" type="xs:string"/>
<xs:element name="foreignSystemId" type="xs:string"/>
...
</xs:complexType>
</xs:element>
</xs:schema>
We are storing this data in a single region as a Customer object for various reasons, so colocation or similar concepts isn't acceptable for our use case (though it would make this infinitely simpler)
Needs
Access Customer by unique email address (globally unique and validated prior to insert)
Access Customer by unique combination of foreign system identifier name and id (again globally unique and validated prior to insert)
We do have access to Elasticsearch if needed, but we really would like to solve these two unique get requests by returning the Customer Object directly. What is the best way to solve this in Gemfire? FWIW, we are using Spring-Data-Gemfire as well.
The simplest case would be to use a query (GemFire OQL) to get what you need...
SELECT c FROM /Customers c, c.emailAddresses e WHERE e.emailAddress = $1
DISCLAIMER: I have not tested the query, but I think this should work.
Also, sense email address is validated and guaranteed to be unique, you could add an Index on this field to make it quicker for searching.
Then using Spring Data GemFire this is pretty straight forward to add a Spring Data Repository method, such as...
public interface CustomersRepository extends GemfireRepository<Customer, Long> {
...
#Query("SELECT c FROM /Customers c, c.emailAddresses e WHERE e.emailAddress = $1")
Customer findByEmailAddress(String emailAddrdess);
}
And then from you service method...
#Service
public class CustomerService {
...
public Customer lookupBy(String emailAddress) {
...
return customerRepo.findByEmailAddress(emailAddress);
}
}
Hope this helps (and answers your question).
#Query("SELECT c FROM /region c, c.emailAddresses email WHERE email.emailAddress = $1")
List<CustomerEntity> findByEmailAddress(String emailAddress);
This part blows up with a stacktrace:
Caused by: java.lang.ClassCastException: com.gemstone.gemfire.cache.query.internal.Undefined cannot be cast to com.gemstone.gemfire.cache.query.SelectResults
What is wrong with my query?
I have very little knowledge in xsd and in an urgent need for a solution to a petty problem.
I need to define an element(named tag) which may have any type and number of child elements(and texts as well) but must not contain an empty string.
Example: <tag1> co<sub1>2</sub1> <b1>laser</b1></tag1>,<tag1>co2</tag1>,<tag1><i1>laser</i1></tag1> are allowed (let's say that even <tag1><i1></i1></tag1> is also allowed). But <tag1></tag1> not allowed. Please let me know if there is a very simple way of doing this.
If you are using XSD 1.1, you can use an assertion to check the condition you describe:
<xs:element name="tag" type="non-empty"/>
<xs:complexType name="non-empty">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:any/>
</xs:sequence>
<xs:assert test="child::* or not(string(.) eq '')"/>
</xs:complexType>
In XSD 1.0, there isn't quite such a simple approach; if I were you and working in XSD 1.0, I'd change the design to something easier to express in XSD 1.0.
In 1.0, it's easy to require that the tag element have one or more children, without constraining the children:
<xs:complexType name="non-empty" mixed="true">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:any/>
</xs:sequence>
</xs:complexType>
<xs:element name="tag" type="non-empty"/>
It's also easy to specify that the tag element can have any non-empty string (I'm taking you at your word here, and allowing strings consisting only of white space -- be careful what you ask for):
<xs:simpleType name="non-empty">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="tag" type="non-empty"/>
What's not possible in 1.0 is (a) declaring an element as having either a simple or a complex type, or (b) constraining the textual content of a complex type with mixed content.
Good luck.
I have a WCF service that expects an object which I'll call StuffContainer. Our client is trying to generate an XML-serialized StuffContainer using JAXB, but it's coming out wrong. They're ending up with type names where they should have property names, so we're not able to deserialize it.
I know nothing about JAXB, but I gather it creates some auto-generated classes based on our XSD, which can be used to build the XML-serialized object.
Here's the relevant snippet of our auto-generated XSD:
<xs:complexType name="StuffContainer">
<xs:sequence>
<xs:element minOccurs="0" name="myStuff" nillable="true" type="tns:ArrayOfStuff"/>
</xs:sequence>
</xs:complexType>
...
<xs:complexType name="ArrayOfStuff">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Stuff" nillable="true" type="tns:Stuff"/>
</xs:sequence>
</xs:complexType>
Our client's code looks something like this:
ObjectFactory objectFactory = new ObjectFactory();
ArrayOfStuff arrayOfStuff = objectFactory.createArrayOfStuff();
JAXBElement<ArrayOfStuff> arrayOfStuffJAXBElement = objectFactory.createArrayOfStuff(arrayOfStuff);
StuffContainer stuffContainer = objectFactory.createStuffContainer();
stuffContainer.setStuff(arrayOfStuffJAXBElement);
Here's the XML they're getting:
<StuffContainer xmlns="..."><ArrayOfStuff>...</ArrayOfStuff></StuffContainer>
But I need it to be:
<StuffContainer xmlns="..."><myStuff>...</myStuff></StuffContainer>
I think this is because the JAXBElement<ArrayOfStuff> that they're getting from the objectFactory has its QName set to "ArrayOfStuff", and this ends up getting used instead of the property name myStuff. But like I said I know nothing about JAXB so I'm not sure what they should be doing differently.
Is there something either that I can change in the XSD, or that I can ask our client to change in their code, so that it generates the correct XML?
There may be multiple methods on the generated ObjectFactory class. The ones corresponding to nested elements have an entire path built into the method name.
I have a VB class in an .asmx file in Visual Studio 2008:
public class foo
public bla as String
end class
It generates the wsdl value:
<s:complexType name="foo">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="bla" type="s:string" />
</s:sequence>
</s:complexType>
But what I want the wsdl to generate is:
<xs:element name="bla" type="xs:string"
sql:datatype="varchar(25)" minOccurs="1" maxOccurs="1">
</xs:element>
Is there a way to do this?
Or can I edit the generated WSDL?
You can use The System.Xml.Serialization.XmlElementAttribute to mark the property IE:
<XmlElement(DataType := "varchar(25)")>
(my vb is a little rusty if this isn't correct
syntax)
You can save off the WSDL and edit it, however, if you change the WSDL, a proxy generated from it may not be able to communicate with your service.
Edit: If you have the target schema, I would suggest that you use xsd.exe or wsdl.exe to generate the classes you need to serialize to valid documents according to that schema.