我有这个服务定义:
[DataContract]
public class Test
{
[DataMember(IsRequired = true)]
public TestArray[] array;
}
[DataContract]
public class TestArray
{
public DateTime? field1;
public string field2;
}
WCFs Metadataprovider(http://localhost/Test?wsdl)生成为:
<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>
问题是(即使它在svcutil.exe神奇地从中生成客户端时也能正常工作)Metadataprovider实际上创建了一个新对象(ArrayOfTestArray),该对象在它生成的代码中不存在
问题:当我尝试从这个WSDL生成JavaClient时,它当然不会认识到这个“ArrayOf”对象根本不是“真正的”对象,而Java类看起来像: / p>
class Test
{
public ArrayOfTestArray array;
}
class ArrayOfTestArray
{
public TestArray[] array;
}
public class TestArray
{
public DateTime? field1;
public string field2;
}
所以,我当然不想要这个额外的课程......有什么建议吗?
谢谢!
答案 0 :(得分:1)
我的建议是按摩XSD文件本身,因为在.NET方面你可能做的事情可能不多。
以下XSLT应该适合您的情况(假设元素和复杂类型在同一个模式文件中):
<?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>
鉴于此输入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>
它将把它变成:
<?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>
这会生成更好的Java类(尽管它仍然为您提供了额外的本地类型):
@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)
我希望这适用于你的问题(双关语!)