C #의 SOAP wsdl에서 작업에 대한 중첩 된 complexType 매개 변수를 가져 오는 방법
WSDL이 있고 하나의 오퍼레이션이 제공되면이를 구문 분석하고 해당 오퍼레이션에 대한 입력 매개 변수를 가져오고 싶습니다.이 예제는 중첩 된 복합 유형이없는 경우에만 작동합니다.
중첩 된 요소 (complexType 및 simpleType 요소 및 속성)가있는 xsd 파일을 구문 분석하는 방법은 무엇입니까?
이를 위해 작동합니다.
http://www.dneonline.com/calculator.asmx?wsdl
즉, 4 개 작업 모두에 대해 올바른 매개 변수를 반환합니다 (Add에는 intA 및 intB와 함께 AddSoapIn이 있습니다 ...).
그러나 이것은 그렇지 않습니다.
http://www.learnwebservices.com/services/hello?WSDL
SayHello에 대한 HelloRequest 만 가져오고 HelloRequest에서 요소 Name을 가져 오지 않습니다.
이것은 특정 SOAP WSDL이 아닌 모든 SOAP WSDL에서 작동해야합니다. 내 말은 일반 구문 분석입니다.
다음은 코드의 관련 부분입니다.
public TheClient(string url) {
wsdlUrl = url;
ReadServiceDescription();
ServiceName = theService.Name;
}
...
void ReadServiceDescription()
{
try
{
XmlTextReader reader=new XmlTextReader (wsdlUrl);
ServiceDescription service=
ServiceDescription.Read(reader);
theService = service;
_services.Add(service);
}
catch (Exception e)
{
throw e;
}
}
private static List<Tuple<string, string>> getParams(string methodName, XmlSchema schemaXML)
{
List<Tuple<string, string>> parameters = new List<Tuple<string, string>>();
ServiceDescription serviceDescription = theService;
XmlSchema xmlSchema;
WebClient client = new WebClient(); ;
//Drill down into the WSDL's complex types to list out the individual schema elements
//and their data types
Types types = serviceDescription.Types;
if (schemaXML != null)
{
xmlSchema = schemaXML;
} else
{
xmlSchema = types.Schemas[0];
}
foreach (object item in xmlSchema.Items)
{
XmlSchemaElement schemaElement = item as XmlSchemaElement;
XmlSchemaComplexType complexType = item as XmlSchemaComplexType;
if (schemaElement != null && methodName == schemaElement.Name)
{
Console.Out.WriteLine("Schema Element: {0}", schemaElement.Name);
XmlSchemaType schemaType = schemaElement.SchemaType;
XmlSchemaComplexType schemaComplexType = schemaType as XmlSchemaComplexType;
if (schemaComplexType != null)
{
XmlSchemaParticle particle = schemaComplexType.Particle;
XmlSchemaSequence sequence = particle as XmlSchemaSequence;
if (sequence != null)
{
foreach (XmlSchemaElement childElement in sequence.Items)
{
Console.Out.WriteLine(" Element/Type: {0}:{1}", childElement.Name, childElement.SchemaTypeName.Name);
parameters.Add(new Tuple<string, string>(childElement.Name, childElement.SchemaTypeName.Name));
}
}
}
}
else if (complexType != null && complexType.Name == methodName)
{
Console.Out.WriteLine("Complex Type: {0}", complexType.Name);
List<Tuple<string, string>> moreparams = OutputElements(complexType.Particle);
if(moreparams != null && moreparams.Count !=0)
{
parameters.AddRange(moreparams);
}
}
//Console.Out.WriteLine();
}
// Loop through all detected imports in the main schema
List<Tuple<string, string>> importparameters = ImportIncludedSchemasRecursively(wsdlUrl, methodName, xmlSchema);
if (importparameters != null && importparameters.Count != 0)
{
parameters.AddRange(importparameters);
}
return parameters;
}
private static List<Tuple<string, string>> ImportIncludedSchemasRecursively(string mainWsdlUrl, string methodName, XmlSchema currentWsdlSchema)
{
List<Tuple<string, string>> parameters = new List<Tuple<string, string>>();
foreach (XmlSchemaObject externalSchema in currentWsdlSchema.Includes)
{
// Read each external schema into a schema object
if (externalSchema is XmlSchemaImport)
{
Uri baseUri = new Uri(mainWsdlUrl);
Uri schemaUri = new Uri(baseUri, ((XmlSchemaExternal)externalSchema).SchemaLocation);
WebClient http = new WebClient();
Stream schemaStream = http.OpenRead(schemaUri);
System.Xml.Schema.XmlSchema schema = XmlSchema.Read(schemaStream, null);
List<Tuple<string, string>> complexparams = getParams(methodName, schema);
if (complexparams != null && complexparams.Count != 0)
{
parameters.AddRange(complexparams);
}
List<Tuple<string, string>> morecomplexparams = ImportIncludedSchemasRecursively(mainWsdlUrl.ToString(), methodName, schema);
if (morecomplexparams != null && morecomplexparams.Count != 0)
{
parameters.AddRange(morecomplexparams);
}
}
}
return parameters.Distinct().ToList();
}
private static List<Tuple<string, string>> OutputElements(XmlSchemaParticle particle)
{
List<Tuple<string, string>> parameters = new List<Tuple<string, string>>();
XmlSchemaSequence sequence = particle as XmlSchemaSequence;
XmlSchemaChoice choice = particle as XmlSchemaChoice;
XmlSchemaAll all = particle as XmlSchemaAll;
if (sequence != null)
{
for (int i = 0; i < sequence.Items.Count; i++)
{
XmlSchemaElement childElement = sequence.Items[i] as XmlSchemaElement;
XmlSchemaSequence innerSequence = sequence.Items[i] as XmlSchemaSequence;
XmlSchemaChoice innerChoice = sequence.Items[i] as XmlSchemaChoice;
XmlSchemaAll innerAll = sequence.Items[i] as XmlSchemaAll;
Console.Out.WriteLine("111 child: {0}", childElement.Name);
if (childElement != null)
{
parameters.Add(new Tuple<string, string>(childElement.Name, childElement.SchemaTypeName.Name));
}
else {
List<Tuple<string, string>> moreparams = OutputElements(sequence.Items[i] as XmlSchemaParticle);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
}
return parameters;
}
else if (choice != null)
{
Console.Out.WriteLine(" Choice");
for (int i = 0; i < choice.Items.Count; i++)
{
XmlSchemaElement childElement = choice.Items[i] as XmlSchemaElement;
XmlSchemaSequence innerSequence = choice.Items[i] as XmlSchemaSequence;
XmlSchemaChoice innerChoice = choice.Items[i] as XmlSchemaChoice;
XmlSchemaAll innerAll = choice.Items[i] as XmlSchemaAll;
Console.Out.WriteLine("222 child: {0}", childElement.Name);
if (childElement != null)
{
parameters.Add(new Tuple<string, string>(childElement.Name, childElement.SchemaTypeName.Name));
}
else
{
List<Tuple<string, string>> moreparams = OutputElements(choice.Items[i] as XmlSchemaParticle);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
}
return parameters;
}
else if (all != null)
{
for (int i = 0; i < all.Items.Count; i++)
{
XmlSchemaElement childElement = all.Items[i] as XmlSchemaElement;
XmlSchemaSequence innerSequence = all.Items[i] as XmlSchemaSequence;
XmlSchemaChoice innerChoice = all.Items[i] as XmlSchemaChoice;
XmlSchemaAll innerAll = all.Items[i] as XmlSchemaAll;
Console.Out.WriteLine("333 child: {0}", childElement.Name);
if (childElement != null)
{
parameters.Add(new Tuple<string, string>(childElement.Name, childElement.SchemaTypeName.Name));
}
else
{
List<Tuple<string, string>> moreparams = OutputElements(all.Items[i] as XmlSchemaParticle);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
}
return parameters;
}
return parameters;
}
SayHello에 대해 getParams를 호출하면 명령 줄에 표시됩니다.

첫 번째 디버그는 49 행 (이전 주석 코드에서;)), 70 행에서 두 번째, OutputElements 함수의 138 행에서 마지막 디버그입니다.
또한 139 행에 null (childElement)이없고 param으로 추가 될 때 complexType (이 경우 HelloRequest)을 가져 오려고했습니다.
복잡한 유형으로 변환하십시오.
XmlSchemaComplexType complexTypeChild = sequence.Items[i] as XmlSchemaComplexType;
SayHello와 유사하게 HelloRequest의 부모가 처리되고이를 다시 호출하는 동일한 함수 OutputElements with complexTypeChild, recursive
그래서 다른 아이가 있으면
그러나 complexTypeChild는 null입니다.
다음과 같은 OutputElements를 얻었습니다.
private static List<Tuple<string, string, string>> OutputElements(XmlSchemaParticle particle, string parentName)
{
List<Tuple<string, string, string>> parameters = new List<Tuple<string, string, string>>();
XmlSchemaSequence sequence = particle as XmlSchemaSequence;
XmlSchemaChoice choice = particle as XmlSchemaChoice;
XmlSchemaAll all = particle as XmlSchemaAll;
if (sequence != null)
{
for (int i = 0; i < sequence.Items.Count; i++)
{
XmlSchemaElement childElement = sequence.Items[i] as XmlSchemaElement;
XmlSchemaSequence innerSequence = sequence.Items[i] as XmlSchemaSequence;
XmlSchemaChoice innerChoice = sequence.Items[i] as XmlSchemaChoice;
XmlSchemaAll innerAll = sequence.Items[i] as XmlSchemaAll;
if (childElement != null)
{
parameters.Add(new Tuple<string, string, string>(childElement.Name, childElement.SchemaTypeName.Name, parentName));
// if it has children
List<Tuple<string, string, string>> moreparams = getParams(childElement.SchemaTypeName.Name, null);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
else {
List<Tuple<string, string, string>> moreparams = OutputElements(sequence.Items[i] as XmlSchemaParticle, parentName);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
}
return parameters;
}
else if (choice != null)
{
Console.Out.WriteLine(" Choice");
for (int i = 0; i < choice.Items.Count; i++)
{
XmlSchemaElement childElement = choice.Items[i] as XmlSchemaElement;
XmlSchemaSequence innerSequence = choice.Items[i] as XmlSchemaSequence;
XmlSchemaChoice innerChoice = choice.Items[i] as XmlSchemaChoice;
XmlSchemaAll innerAll = choice.Items[i] as XmlSchemaAll;
if (childElement != null)
{
parameters.Add(new Tuple<string, string, string>(childElement.Name, childElement.SchemaTypeName.Name, parentName));
}
else
{
List<Tuple<string, string, string>> moreparams = OutputElements(choice.Items[i] as XmlSchemaParticle, parentName);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
}
return parameters;
}
else if (all != null)
{
for (int i = 0; i < all.Items.Count; i++)
{
XmlSchemaElement childElement = all.Items[i] as XmlSchemaElement;
XmlSchemaSequence innerSequence = all.Items[i] as XmlSchemaSequence;
XmlSchemaChoice innerChoice = all.Items[i] as XmlSchemaChoice;
XmlSchemaAll innerAll = all.Items[i] as XmlSchemaAll;
if (childElement != null)
{
parameters.Add(new Tuple<string, string, string>(childElement.Name, childElement.SchemaTypeName.Name, parentName));
}
else
{
List<Tuple<string, string, string>> moreparams = OutputElements(all.Items[i] as XmlSchemaParticle, parentName);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
}
return parameters;
}
return parameters;
}
이후 5 줄 참조
// if it has children
그래서 발견되면 자식이 있는지 확인하고 해당 작업을 호출하는 봉투를 만들 때 사용할 수 있도록 매개 변수에 부모 매개 변수 / 요소를 추가했습니다.
답변
WSDL을 가져 와서 스키마 섹션을 제거했습니다. 그런 다음 섹션에서 xsd.exe를 실행하고 다음 C # 클래스로 이동하십시오.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System.Xml.Serialization;
//
// This source code was auto-generated by xsd, Version=4.0.30319.33440.
//
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://learnwebservices.com/services/hello")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://learnwebservices.com/services/hello", IsNullable=false)]
public partial class SayHello {
private helloRequest helloRequestField;
/// <remarks/>
public helloRequest HelloRequest {
get {
return this.helloRequestField;
}
set {
this.helloRequestField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://learnwebservices.com/services/hello")]
public partial class helloRequest {
private string nameField;
/// <remarks/>
public string Name {
get {
return this.nameField;
}
set {
this.nameField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://learnwebservices.com/services/hello")]
public partial class helloResponse {
private string messageField;
/// <remarks/>
public string Message {
get {
return this.messageField;
}
set {
this.messageField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://learnwebservices.com/services/hello")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://learnwebservices.com/services/hello", IsNullable=false)]
public partial class SayHelloResponse {
private helloResponse helloResponseField;
/// <remarks/>
public helloResponse HelloResponse {
get {
return this.helloResponseField;
}
set {
this.helloResponseField = value;
}
}
}
이제 작동합니다. 문제는 처음에 코드를 사용한 솔루션이었습니다. 여기
실제로 복잡한 유형의 하나의 깊은 수준을 사용하여 wsdl 유형에 대해 사용자 정의되었으며 모든 wsdl에서 작업해야했습니다. 이제 몇 가지 작업을 시도했지만 작동하지만 일부 예제를 찾을 수 있습니다. 작동하지 않는 복잡한 항목,이 경우 여기로 돌아와 고정 코드를 게시하겠습니다.
어쨌든 해결책은 적어도 지금은 문서 및 rpc 및 soap 1.1 및 soap 1.2 wsdls에서 작동하는 것처럼 보입니다.
private static List<Tuple<string, string, string>> getParams(string methodName, XmlSchema schemaXML)
{
List<Tuple<string, string, string>> parameters = new List<Tuple<string, string, string>>();
ServiceDescription serviceDescription = theService;
XmlSchema xmlSchema;
WebClient client = new WebClient(); ;
//Drill down into the WSDL's complex types to list out the individual schema elements
//and their data types
Types types = serviceDescription.Types;
if (schemaXML != null)
{
xmlSchema = schemaXML;
} else
{
xmlSchema = types.Schemas[0];
}
foreach (object item in xmlSchema.Items)
{
XmlSchemaElement schemaElement = item as XmlSchemaElement;
XmlSchemaComplexType complexType = item as XmlSchemaComplexType;
if (schemaElement != null && methodName == schemaElement.Name)
{
Console.Out.WriteLine("Schema Element: {0}", schemaElement.Name);
XmlSchemaType schemaType = schemaElement.SchemaType;
XmlSchemaComplexType schemaComplexType = schemaType as XmlSchemaComplexType;
if (schemaComplexType != null)
{
XmlSchemaParticle particle = schemaComplexType.Particle;
XmlSchemaSequence sequence = particle as XmlSchemaSequence;
if (sequence != null)
{
foreach (XmlSchemaElement childElement in sequence.Items)
{
parameters.Add(new Tuple<string, string, string>(childElement.Name, childElement.SchemaTypeName.Name, schemaElement.Name));
}
}
}
}
else if (complexType != null && complexType.Name == methodName)
{
Console.Out.WriteLine("Complex Type: {0}", complexType.Name);
List<Tuple<string, string, string>> moreparams = OutputElements(complexType.Particle, complexType.Name);
if(moreparams != null && moreparams.Count !=0)
{
parameters.AddRange(moreparams);
}
}
}
// Loop through all detected imports in the main schema
List<Tuple<string, string, string>> importparameters = ImportIncludedSchemasRecursively(wsdlUrl, methodName, xmlSchema);
if (importparameters != null && importparameters.Count != 0)
{
parameters.AddRange(importparameters);
}
return parameters;
}
private static List<Tuple<string, string, string>> ImportIncludedSchemasRecursively(string mainWsdlUrl, string methodName, XmlSchema currentWsdlSchema)
{
List<Tuple<string, string, string>> parameters = new List<Tuple<string, string, string>>();
foreach (XmlSchemaObject externalSchema in currentWsdlSchema.Includes)
{
// Read each external schema into a schema object
if (externalSchema is XmlSchemaImport)
{
Uri baseUri = new Uri(mainWsdlUrl);
Uri schemaUri = new Uri(baseUri, ((XmlSchemaExternal)externalSchema).SchemaLocation);
WebClient http = new WebClient();
Stream schemaStream = http.OpenRead(schemaUri);
System.Xml.Schema.XmlSchema schema = XmlSchema.Read(schemaStream, null);
List<Tuple<string, string, string>> complexparams = getParams(methodName, schema);
if (complexparams != null && complexparams.Count != 0)
{
parameters.AddRange(complexparams);
}
List<Tuple<string, string, string>> morecomplexparams = ImportIncludedSchemasRecursively(mainWsdlUrl.ToString(), methodName, schema);
if (morecomplexparams != null && morecomplexparams.Count != 0)
{
parameters.AddRange(morecomplexparams);
}
}
}
return parameters.Distinct().ToList();
}
private static List<Tuple<string, string, string>> OutputElements(XmlSchemaParticle particle, string parentName)
{
List<Tuple<string, string, string>> parameters = new List<Tuple<string, string, string>>();
XmlSchemaSequence sequence = particle as XmlSchemaSequence;
XmlSchemaChoice choice = particle as XmlSchemaChoice;
XmlSchemaAll all = particle as XmlSchemaAll;
if (sequence != null)
{
for (int i = 0; i < sequence.Items.Count; i++)
{
XmlSchemaElement childElement = sequence.Items[i] as XmlSchemaElement;
XmlSchemaSequence innerSequence = sequence.Items[i] as XmlSchemaSequence;
XmlSchemaChoice innerChoice = sequence.Items[i] as XmlSchemaChoice;
XmlSchemaAll innerAll = sequence.Items[i] as XmlSchemaAll;
if (childElement != null)
{
parameters.Add(new Tuple<string, string, string>(childElement.Name, childElement.SchemaTypeName.Name, parentName));
// if it has children
List<Tuple<string, string, string>> moreparams = getParams(childElement.SchemaTypeName.Name, null);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
else {
List<Tuple<string, string, string>> moreparams = OutputElements(sequence.Items[i] as XmlSchemaParticle, parentName);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
}
return parameters;
}
else if (choice != null)
{
Console.Out.WriteLine(" Choice");
for (int i = 0; i < choice.Items.Count; i++)
{
XmlSchemaElement childElement = choice.Items[i] as XmlSchemaElement;
XmlSchemaSequence innerSequence = choice.Items[i] as XmlSchemaSequence;
XmlSchemaChoice innerChoice = choice.Items[i] as XmlSchemaChoice;
XmlSchemaAll innerAll = choice.Items[i] as XmlSchemaAll;
if (childElement != null)
{
parameters.Add(new Tuple<string, string, string>(childElement.Name, childElement.SchemaTypeName.Name, parentName));
}
else
{
List<Tuple<string, string, string>> moreparams = OutputElements(choice.Items[i] as XmlSchemaParticle, parentName);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
}
return parameters;
}
else if (all != null)
{
for (int i = 0; i < all.Items.Count; i++)
{
XmlSchemaElement childElement = all.Items[i] as XmlSchemaElement;
XmlSchemaSequence innerSequence = all.Items[i] as XmlSchemaSequence;
XmlSchemaChoice innerChoice = all.Items[i] as XmlSchemaChoice;
XmlSchemaAll innerAll = all.Items[i] as XmlSchemaAll;
if (childElement != null)
{
parameters.Add(new Tuple<string, string, string>(childElement.Name, childElement.SchemaTypeName.Name, parentName));
}
else
{
List<Tuple<string, string, string>> moreparams = OutputElements(all.Items[i] as XmlSchemaParticle, parentName);
if (moreparams != null && moreparams.Count != 0)
{
parameters.AddRange(moreparams);
}
}
}
return parameters;
}
return parameters;
}
이것은 파싱 된 wsdl이 주어지면 초기 / 원본 게시물의 코드를 참조하여 작업에 매개 변수를 제공하여 각각의 부모와 함께 호출합니다.