WSDL automatically generated by WCF
i've got 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 is ( even if it works when svcutil.exe magic开发者_JAVA技巧ally generates a client from it ) that the Metadataprovider actually creates a new object ( ArrayOfTestArray ) which is not existent in the code it was generated from
Problem: When i try to generate a JavaClient from this WSDL, it - of course - doesn't recognize that this "ArrayOf" object isn't a "real" object at all and the Java class looks something like:
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 additional class of course... any suggestions?
Thanks!
My suggestion is to massage the XSD file itself, since there's probably not much you can do on the .NET side of things.
The following XSLT should work in your case (provided the element and the 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 input XSD:
<?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>
it 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 produces nicer Java classes (although it still gives you an extra, 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)
I hope this applies to your problem (pun intended!)
精彩评论