由WCF自动生成的WSDL

4

我有这个服务定义:

[DataContract]
public class Test
{

    [DataMember(IsRequired = true)]
    public TestArray[] array;
}

[DataContract]
public class TestArray
{
   public DateTime? field1;
   public string field2;
}

WCF的元数据提供程序(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 生成 Java 客户端时,它当然无法识别这个 "ArrayOf" 对象根本不是一个真正的对象,因此 Java 类看起来像这样:
class Test
{
   public ArrayOfTestArray array;
}

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

所以,我不想要这个额外的类... 有什么建议吗?
谢谢!

不确定这是否有帮助,但我目前正在使用 J2EE Web 服务,并且在 WSDL 中看到了大量的 ArrayOfXXXX 类。也许这是标准做法?不确定。 - Tad Donaghe
我不是.NET专业人士,所以我不太确定.NET中的代码是如何生成的,但看起来你有'ArrayOfTestArray'的原因是因为你已经声明了'TestArray'为必需,并且代码生成器正在生成你要求的内容。Java类是从wsdl生成的,该类型已定义,因此类似乎已正确生成。我没有发布答案,因为我真的不确定.NET如何为Web服务生成代码。 - ChadNC
当我询问我的一些同事时,他们说ArrayOf结构是标准行为...嗯,到目前为止我对Java方面的问题没有什么头绪。 - David
1个回答

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)

希望这对你的问题有所帮助(双关语!)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接