【发布时间】:2020-11-19 10:29:20
【问题描述】:
拥有一个 WSDL 并给定它提供的一个操作,我想解析它并获取该操作的输入参数,此示例仅在没有嵌套复杂类型时才适用于我:
为此它有效:
http://www.dneonline.com/calculator.asmx?wsdl
这意味着它为所有 4 个操作返回正确的参数(Add 具有带 intA 和 intB 的 AddSoapIn...)
但对于这个没有:
http://www.learnwebservices.com/services/hello?WSDL
它只获取 SayHello 的 HelloRequest,而不从 HelloRequest 中获取元素名称。
这应该适用于任何而非特定的 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 行。
我还尝试获取 complexType,在本例中为 HelloRequest,当第 139 行不为空(childElement)并添加为参数时,
并将其转换为复杂类型:
XmlSchemaComplexType complexTypeChild = sequence.Items[i] as XmlSchemaComplexType;
类似于SayHello,HelloRequest的parent被处理,再次调用同样的函数OutputElements与complexTypeChild,递归
所以如果有其他孩子会工作
但 complexTypeChild 为空。
我偶然发现了这样的 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
所以如果找到然后检查是否有子元素,我还将父参数/元素添加到参数中,以便在创建信封时使用它来调用该操作。
【问题讨论】:
标签: c# parsing soap wsdl complextype