WSDL is automatically generated by WCF

I have this servicedefinition:

[DataContract] public class Test { [DataMember(IsRequired = true)] public TestArray[] array; } [DataContract] public class TestArray { public DateTime? field1; public string field2; } 

which WCFs Metadataprovider ( http: // localhost / Test? wsdl ) generates as:

 <xs:complexType name="ArrayOfTestArray"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="array" nillable="true" type="tns:TestArray"/> </xs:sequence> </xs:complexType> <xs:complexType name="OpenBalanceInvoice"> <xs:sequence> <xs:element name="field1" nillable="true" type="xs:dateTime"/> <xs:element name="field2" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> 

The problem (even if it works when svcutil.exe magically generates a client from it) that Metadataprovider actually creates a new object (ArrayOfTestArray) that does not exist in the code that it was created from

Problem: when I try to create a JavaClient from this WSDL, it certainly does not recognize that this ArrayOf is not a β€œreal” object at all, and the Java class looks something like this: / p>

 class Test { public ArrayOfTestArray array; } class ArrayOfTestArray { public TestArray[] array; } public class TestArray { public DateTime? field1; public string field2; } 

So, I don't want this extra class, of course ... any suggestions?

Thanks!

+4
source share
1 answer

My suggestion is to massage the XSD file itself, since there is probably not much that can be done on the .NET side.

The following XSLT should work in your case (if the element and complex types are in the same schema file):

 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsl:template match="xsd:complexType[@name]"> <!-- This templace filters out any complexTypes with a name starting with 'ArrayOf' --> <xsl:if test="not(starts-with(@name, 'ArrayOf'))"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:apply-templates /> </xsl:copy> </xsl:if> </xsl:template> <xsl:template match="xsd:element[@type]"> <!-- This templace inlines any elements referencing a type starting with 'ArrayOf' --> <xsl:variable name="typeName"> <xsl:choose> <xsl:when test="contains(@type, ':')"> <xsl:value-of select="substring-after(@type, ':')" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="@type" /> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose><!-- Should we inline? --> <xsl:when test="starts-with($typeName, 'ArrayOf')"> <!-- Yep, inline it, but wrap in a sequence! --> <xsl:apply-templates select="xsd:annotation" /> <xsd:element> <!-- copy over attributes such as name, minOccurs, maxOccurs, nillable --> <xsl:copy-of select="@*[local-name(.) != 'type']" /> <xsl:comment> Inlined from <xsl:value-of select="@type" />): </xsl:comment> <xsd:complexType> <xsl:apply-templates select="//xsd:complexType[@name=$typeName]/*" /> </xsd:complexType> <xsl:comment>End of inlined element</xsl:comment> </xsd:element> <xsl:apply-templates select="xsd:attribute | xsd:attributeGroup | xsd:attributeGroup" /> </xsl:when> <xsl:otherwise> <!-- Nah, just copy --> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:apply-templates /> </xsl:copy> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- General copy rule --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:apply-templates /> </xsl:copy> </xsl:template> </xsl:stylesheet> 

Given this XSD input:

 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/ExtensionFlattener" xmlns:tns="http://www.example.org/ExtensionFlattener" elementFormDefault="qualified"> <xs:element name="SomeElement"> <xs:complexType> <xs:sequence> <xs:element name="First" type="xs:string" /> <xs:element name="Second" minOccurs="0" type="tns:ArrayOfTestArray" nillable="true"/> <xs:element name="Third" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="ArrayOfTestArray"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="array" nillable="true" type="tns:TestArray" /> </xs:sequence> </xs:complexType> <xs:complexType name="TestArray"> <xs:sequence> <xs:element name="field1" nillable="true" type="xs:dateTime" /> <xs:element name="field2" nillable="true" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:schema> 

he will turn it into:

 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/ExtensionFlattener" targetNamespace="http://www.example.org/ExtensionFlattener" elementFormDefault="qualified"> <xs:element name="SomeElement"> <xs:complexType> <xs:sequence> <xs:element name="First" type="xs:string" /> <xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Second" minOccurs="0" nillable="true"> <!-- Inlined from tns:ArrayOfTestArray): --> <xsd:complexType> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="array" nillable="true" type="tns:TestArray" /> </xs:sequence> </xsd:complexType> <!--End of inlined element --> </xsd:element> <xs:element name="Third" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="TestArray"> <xs:sequence> <xs:element name="field1" nillable="true" type="xs:dateTime" /> <xs:element name="field2" nillable="true" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:schema> 

This gives more nice Java classes (although it still gives you an additional, local, type):

 @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "first", "second", "third" }) @XmlRootElement(name = "SomeElement") public class SomeElement { @XmlElement(name = "First", required = true) protected String first; @XmlElementRef(name = "Second", namespace = "http://www.example.org/ExtensionFlattener", type = JAXBElement.class) protected JAXBElement<SomeElement.Second> second; @XmlElement(name = "Third", required = true) protected String third; // Plus getters and setters @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "array" }) public static class Second { @XmlElement(nillable = true) protected List<TestArray> array; // plus getter } } (plus the other class) 

Hope this applies to your problem (pun intended!)

+1
source

Source: https://habr.com/ru/post/1300649/


All Articles