parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

Ответ

virusav 18.03.2016 20:33

Выкладываю код, т.к. не вижу, как тут файл прикрепить.)

1. Код писался 10 месяцев назад и с тех пор не правился.
2. Класс был изначально создан для своих целей, а не как универсальный инструмент для работы с SOAP.
3. Тестирование проводилось на 3 разных структурах WDSL в режимах Клиент и Сервер. Тесты прошли успешно.
4. Есть возможность получить ответ в случае ошибки (Fault).
5. Для знатоков код покажется "бредом сивой кобылы", но я рад и тому, что удалось самому что-то сделать, что работает.)
6. При наличии WSDL со структурой, где используются самописные типы или импорт типов данный класс вряд ли сработает, т.к. на момент написания такой функционал не был нужен.

Сам класс:
########################################
@CLASS
SOAP



########################################
@SET_address[sValue]
$sAddress[$sValue]



########################################
@GET_address[]
$result[$sAddress]



########################################
@SET_user[sValue]
$sUser[$sValue]



########################################
@GET_user[]
$result[$sUser]



########################################
@SET_password[sValue]
$sPassword[$sValue]



########################################
@GET_password[]
$result[$sPassword]



########################################
@SET_charset[sValue]
$sCharset[$sValue]



########################################
@GET_charset[]
$result[$sCharset]



########################################
@create[hInput]
	$self.user[$hInput.sUser]
	$self.password[$hInput.sPassword]
	$self.charset[^if(def $hInput.sCharset){$hInput.sCharset}{UTF-8}]



########################################
@loadURL[hInput][key;value]
	$result[^curl:load[
		$.mode[text]
		$.timeout(60)
		$.charset[$self.charset]
		$.url[^taint[as-is][$hInput.sURL]]
		$.userpwd[${self.user}:$self.password]
		^if(def $hInput.hData){
			^if(^hInput.hData.contains[postfields]){
				$.post(true)
			}
			^hInput.hData.foreach[key;value]{
				$.[$key][$value]
			}
		}
		$.ssl_verifypeer[]
	]]



########################################
@sendRequest[hInput][fFile]
	$fFile[^self.loadURL[
		$.sURL[$self.address]
		$.hData[
			$.postfields[^taint[as-is][^if(def $hInput.sRequest){$hInput.sRequest}{^self.getRequest[$hInput.hWSDL;$hInput.sOperation;$hInput.hRequest]}]]
		]
	]]
	$result[^self.getResponse[$hInput.hWSDL;$fFile.text]]



########################################
@parseWSDL[sWSDL;bLoad;bLocal][fFile;xdData;hWSDL;key;value;sNodeName;key1;value1;key2;value2;sNodeName1;key3;value3]
	$bLoad($bLoad eq "1")
	$bLocal($bLocal eq "1")
	^if($bLoad){
		^if(!$bLocal){
			$fFile[^self.loadURL[
				$.sURL[$sWSDL]
				$.hData[
					$.postfields[]
				]
			]]
			$xdData[^xdoc::create{^taint[as-is][$fFile.text]}]
		}{
			$xdData[^xdoc::load[$sWSDL]]
		}
	}{
		$xdData[^xdoc::create{^taint[as-is][$sWSDL]}]
	}
	$hWSDL[
		$.definitions[^hash::create[]]
		$.service[^hash::create[]]
		$.binding[^hash::create[]]
		$.porttype[^hash::create[]]
		$.message[^hash::create[]]
		$.types[^hash::create[]]
	]
	^if(^xdData.hasChildNodes[] && ^xdData.childNodes.0.nodeName.lower[] eq "definitions" && ^xdData.childNodes.0.hasChildNodes[]){
		$hWSDL.definitions.ns[^self.getNS[$xdData.childNodes.0]]
		^xdData.childNodes.0.attributes.foreach[key;value]{
			$hWSDL.definitions.[$key][$value.nodeValue]
		}
		^xdData.childNodes.0.childNodes.foreach[;value]{
			^if($value.nodeType==1 && ^value.hasChildNodes[]){
				$sNodeName[^value.nodeName.lower[]]
				^switch[$sNodeName]{
					^case[types]{
						^value.childNodes.foreach[;value1]{
							^if($value1.nodeType==1 && ^value1.nodeName.lower[] eq "schema" && ^value1.hasChildNodes[]){
								$hWSDL.types.[$value1.attributes.targetNamespace.nodeValue][
									$.ns[^self.getNS[$value1]]
									$.prefix[$value1.prefix]
									$.type[^hash::create[]]
									$.element[^hash::create[]]
								]
								^value1.childNodes.foreach[;value2]{
									^if($value2.nodeType==1 && ^value2.hasChildNodes[]){
										$sNodeName1[^value2.nodeName.lower[]]
										^switch[$sNodeName1]{
											^case[complextype]{
												$hWSDL.types.[$value1.attributes.targetNamespace.nodeValue].type.[$value2.attributes.name.nodeValue][
													$.prefix[$value2.prefix]
													$.field[^self.getComplexType[$value2]]
												]
											}
											^case[element]{
												^value2.childNodes.foreach[;value3]{
													^if($value3.nodeType==1 && ^value3.nodeName.lower[] eq "complextype" && ^value3.hasChildNodes[]){
														$hWSDL.types.[$value1.attributes.targetNamespace.nodeValue].element.[$value2.attributes.name.nodeValue][
															$.prefix[$value3.prefix]
															$.field[^self.getComplexType[$value3]]
														]
													}
												}
											}
										}
									}
								}
							}
						}
					}
					^case[message]{
						$hWSDL.message.[$value.attributes.name.nodeValue][^hash::create[]]
						^value.childNodes.foreach[;value1]{
							^if($value1.nodeType==1 && ^value1.nodeName.lower[] eq "part"){
								$hWSDL.message.[$value.attributes.name.nodeValue].[$value1.attributes.name.nodeValue][
									$.element[$value1.attributes.element.nodeValue]
									$.type[$value1.attributes.type.nodeValue]
									$.data_type[^if(def $value1.attributes.element.nodeValue){element}{type}]
									$.part[1]
								]
							}
						}
					}
					^case[porttype]{
						$hWSDL.porttype.[$value.attributes.name.nodeValue][^hash::create[]]
						^value.childNodes.foreach[;value1]{
							^if($value1.nodeType==1 && ^value1.nodeName.lower[] eq "operation" && ^value1.hasChildNodes[]){
								$hWSDL.porttype.[$value.attributes.name.nodeValue].[$value1.attributes.name.nodeValue][^hash::create[]]
								^value1.childNodes.foreach[;value2]{
									^if($value2.nodeType==1){
										$hWSDL.porttype.[$value.attributes.name.nodeValue].[$value1.attributes.name.nodeValue].[$value2.nodeName][$value2.attributes.message.nodeValue]
									}
								}
							}
						}
					}
					^case[binding]{
						$hWSDL.binding.[$value.attributes.name.nodeValue][
							$.porttype[$value.attributes.type.nodeValue]
							$.operation[^hash::create[]]
						]
						^value.childNodes.foreach[;value1]{
							^if($value1.nodeType==1 && ^value1.nodeName.lower[] eq "operation" && ^value1.hasChildNodes[]){
								^value1.childNodes.foreach[;value2]{
									^if($value2.nodeType==1 && ^value2.nodeName.lower[] eq "operation"){
										$hWSDL.binding.[$value.attributes.name.nodeValue].operation.[$value1.attributes.name.nodeValue][$value2.attributes.soapAction.nodeValue]
									}
								}
							}
						}
					}
					^case[service]{
						$hWSDL.service.name[$value.attributes.name.nodeValue]
						$hWSDL.service.port[^hash::create[]]
						^value.childNodes.foreach[;value1]{
							^if($value1.nodeType==1 && ^value1.nodeName.lower[] eq "port"){
								$hWSDL.service.port.[$value1.attributes.name.nodeValue][
									$.binding[$value1.attributes.binding.nodeValue]
								]
								^value1.childNodes.foreach[;value2]{
									^if(^value2.nodeName.lower[] eq "address"){
										$hWSDL.service.port.[$value1.attributes.name.nodeValue].prefix[$value2.prefix]
										$hWSDL.service.port.[$value1.attributes.name.nodeValue].address[$value2.attributes.location.nodeValue]
										^if(^hWSDL.service.port._count[]==1){
											$self.address[^taint[as-is][$value2.attributes.location.nodeValue]]
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	$result[$hWSDL]



########################################
@getNS[xnData;sPrefix;sNodeName][hData;xdTemp;xnTemp;sTemp;tTemp]
	$hData[^hash::create[]]
	$xdTemp[^xdoc::create[uuid]]
	$xnTemp[^xdTemp.documentElement.appendChild[$xnData]]
	$sTemp[^xdTemp.string[]]
	$sTemp[^sTemp.match[<^if(def $xnData.prefix){${xnData.prefix}:}${xnData.nodeName}([^^>]+?)>][i]{
		$tTemp[^match.1.match[xmlns:([^^=]+?)="([^^"]+?)"][gi]]
		^tTemp.sort{$tTemp.2}[asc]
		^tTemp.menu{
			^if($tTemp.1 ne "xs"){
				$hData.[$tTemp.1][$tTemp.2]
			}
		}
	}]
	$result[$hData]



########################################
@getComplexType[xdData][key;value;hData;key1;value1;key2;value2]
	^xdData.childNodes.foreach[;value]{
		^if($value.nodeType==1 && ^value.hasChildNodes[]){
			$hData[^hash::create[]]
			^value.childNodes.foreach[;value1]{
				^if($value1.nodeType==1 && ^value1.nodeName.lower[] eq "element"){
					$hData.[$value1.attributes.name.nodeValue][
						$.prefix[$value1.prefix]
						^value1.attributes.foreach[key2;value2]{
							^if($key2 ne "name"){
								$.[$key2][$value2.nodeValue]
							}
						}
					]
				}
			}
		}
	}
	$result[$hData]



########################################
@getOperationType[sAction;sActionSide]
	$result[^switch[$sAction]{
		^case[request]{^switch[$sActionSide]{
			^case[server]{output}
			^case[DEFAULT]{input}
		}}
		^case[response]{^switch[$sActionSide]{
			^case[server]{input}
			^case[DEFAULT]{output}
		}}
	}]



########################################
@getRequest[hWSDL;sOperation;hRequest;sActionSide][hNS;iNum;sHTML;sOperationType;key;value;tTemp;key1;value1;tField;key2;value2]
	$hNS[^hash::create[]]
	$iNum(0)
	$sHTML[<?xml version="1.0" encoding="$self.charset"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"^hWSDL.definitions.ns.foreach[key;value]{ xmlns:^iNum.inc[]$hNS.[$value][ns$iNum]ns$iNum="$value"}><SOAP-ENV:Body>]
	$sOperationType[^getOperationType[request;$sActionSide]]
	^hWSDL.porttype.foreach[key;value]{
		^if(^value.contains[$sOperation]){
			$tTemp[^value.[$sOperation].[$sOperationType].split[:;h]]
			^if(^hWSDL.message.contains[$tTemp.1]){
				$sHTML[$sHTML<$hNS.[$hWSDL.definitions.ns.[$tTemp.0]]:$sOperation>]
				^hWSDL.message.[$tTemp.1].foreach[key1;value1]{
					$tField[^value1.[$value1.data_type].split[:;h]]
					^if(^hWSDL.types.contains[$hWSDL.definitions.ns.[$tTemp.0]] && ^hWSDL.types.[$hWSDL.definitions.ns.[$tTemp.0]].contains[$value1.data_type] && ^hWSDL.types.[$hWSDL.definitions.ns.[$tTemp.0]].[$value1.data_type].contains[$tField.1]){
						^if($value1.data_type eq "type"){
							$sHTML[$sHTML<$key1>]
						}
						^hWSDL.types.[$hWSDL.definitions.ns.[$tTemp.0]].[$value1.data_type].[$tField.1].field.foreach[key2;value2]{
							$sHTML[^self.getRequestFieldValue[$sHTML;$hWSDL;^if(!^value2.contains[minOccurs]){$hRequest}{$hRequest.[$key2]};$hNS;$hWSDL.definitions.ns.[$tTemp.0];$hWSDL.types.[$hWSDL.definitions.ns.[$tTemp.0]].ns;$key2;$value2]]
						}
						^if($value1.data_type eq "type"){
							$sHTML[$sHTML</$key1>]
						}
					}{
						$sHTML[^self.getRequestFieldValue[$sHTML;$hWSDL;$hRequest;$hNS;$hWSDL.definitions.ns.[$tTemp.0];;$key1;$value1]]
					}
				}
				$sHTML[$sHTML</$hNS.[$hWSDL.definitions.ns.[$tTemp.0]]:$sOperation>]
				^break[]
			}
			^break[]
		}
	}
	$result[$sHTML</SOAP-ENV:Body></SOAP-ENV:Envelope>]



########################################
@getRequestFieldValue[sHTML;hWSDL;hRequest;hNS;sFieldNS;hFieldNS;sField;hField][tField;sNS;key;value;key1;value1;sTemp]
	$tField[^hField.type.split[:;h]]
	$sNS[$hFieldNS.[$tField.0]]
	^if(^hWSDL.types.contains[$sNS] && ^hWSDL.types.[$sNS].contains[type] && ^hWSDL.types.[$sNS].type.contains[$tField.1]){
		^if(!^hField.contains[minOccurs]){
			$hRequest[
				$.1[$hRequest.[$sField]]
			]
		}
		^if(def $hRequest){
			^hRequest.foreach[;value]{
				$sHTML[$sHTML<$hNS.[$sFieldNS]:$sField>]
				^hWSDL.types.[$sNS].type.[$tField.1].field.foreach[key1;value1]{
					$sHTML[^self.getRequestFieldValue[$sHTML;$hWSDL;$value;$hNS;$sNS;$hWSDL.types.[$sNS].ns;$key1;$value1]]
				}
				$sHTML[$sHTML</$hNS.[$sFieldNS]:$sField>]
			}
		}
	}{
		^if(!($hRequest.[$sField] is hash)){
			$hRequest.[$sField][
				$.1[$hRequest.[$sField]]
			]
		}
		$sTemp[^if(!^hField.contains[part]){$hNS.[$sFieldNS]:}]
		$sHTML[${sHTML}^hRequest.[$sField].foreach[;value]{^if(def $value){<${sTemp}$sField>^switch[$tField.1]{
			^case[boolean]{^if($value){true}{false}}
			^case[date]{^formatDate[$value;1;0]}
			^case[dateTime]{^formatDate[$value;1]}
			^case[decimal]{^value.format[%.2f]}
			^case[integer;int]{^value.int(0)}
			^case[string]{$value}
		}</${sTemp}$sField>}(!^hField.contains[minOccurs]){<${sTemp}$sField xsi:nil="true"/>}}]
	}
	$result[$sHTML]



########################################
@getResponse[hWSDL;sHTML;sActionSide][hTemp;fFile;key;value;sTemp;xdData;sOperationType;hData;xnData;hNS;sOperation;sType;tTemp;key1;value1;tField;key2;value2]
	$hTemp[^hash::create[]]
	$fFile[^file::create[text;temp.txt;$sHTML;
		$.charset[$self.charset]
	]]
	$sHTML[^fFile.text.match[<\s*\?\s*xml(?:(?!\s*\?\s*>).+?)\s*\?\s*>][i]{}]
	^hWSDL.definitions.ns.foreach[key;value]{
		$sTemp[^sHTML.match[^^\s*<([^^>]+?)>][]{
			^if(^match.1.pos[xmlns:$key=]==-1){
				$hTemp.[$value][$key]
				$sHTML[^sHTML.match[\s*<([^^>]+?)>][]{<$match.1 xmlns:$key="$value">}]
			}
		}]
	}
	$sHTML[^sHTML.match[ xmlns="([^^"]+?)"][gi]{ xmlns="$hTemp.[$match.1]:$match.1"}]
	$xdData[^xdoc::create{<?xml version="1.0" encoding="$self.charset"?>^taint[as-is][$sHTML]}]
	$sOperationType[^getOperationType[response;$sActionSide]]
	$hData[^hash::create[]]
	^xdData.childNodes.0.childNodes.foreach[;value]{
		^if($value.nodeType==1 && ^value.hasChildNodes[] && $value.nodeName eq "Body"){
			$xnData[$value]
			$hTemp[^xnData.getElementsByTagName[Fault]]
			^if(def $hTemp && $hTemp.0.nodeType==1 && ^hTemp.0.hasChildNodes[]){
				$hData._ERROR[^hash::create[]]
				^hTemp.0.childNodes.foreach[;value1]{
					^if($value1.nodeType==1){
						$hData._ERROR.[$value1.nodeName][$value1.childNodes.0.nodeValue]
					}
				}
			}{
				$hNS[^self.getNS[$xdData.childNodes.0]]
				^xnData.childNodes.foreach[;value]{
					^if($value.nodeType==1){
						^hNS.add[^self.getNS[$value]]
						$sOperation[^value.nodeName.match[Response^$][im]{}]
						$sType[$hNS.[$value.prefix]]
						^hWSDL.porttype.foreach[key;value]{
							^if(^value.contains[$sOperation]){
								$tTemp[^value.[$sOperation].[$sOperationType].split[:;h]]
								^if(^hWSDL.message.contains[$tTemp.1]){
									^hWSDL.message.[$tTemp.1].foreach[key1;value1]{
										$tField[^value1.[$value1.data_type].split[:;h]]
										^if(^hWSDL.types.contains[$sType] && ^hWSDL.types.[$sType].contains[$value1.data_type] && ^hWSDL.types.[$sType].[$value1.data_type].contains[$tField.1]){
											^hWSDL.types.[$sType].[$value1.data_type].[$tField.1].field.foreach[key2;value2]{
												^self.getResponseFieldValue[$hData;$hWSDL;^xnData.getElementsByTagName[$key2];$hWSDL.types.[$sType].ns;$key2;$value2]
											}
										}{
											^self.getResponseFieldValue[$hData;$hWSDL;^xnData.getElementsByTagName[$key1];$hWSDL.types.[$sType].ns;$key1;$value1]
										}
									}
									^break[]
								}
							}
						}
					}
				}
			}
		}
	}
	$result[$hData]



########################################
@getResponseFieldValue[hData;hWSDL;hResponse;hFieldNS;sField;hField][tField;sNS;key;value;key1;value1;hTemp;iTemp;iNum;Temp;hKey;hValue]
	$tField[^hField.type.split[:;h]]
	$sNS[$hFieldNS.[$tField.0]]
	^if(^hWSDL.types.contains[$sNS] && ^hWSDL.types.[$sNS].contains[type] && ^hWSDL.types.[$sNS].type.contains[$tField.1]){
		$hData.[$sField][^hash::create[]]
		^hResponse.foreach[key;value]{
			^hWSDL.types.[$sNS].type.[$tField.1].field.foreach[key1;value1]{
				^if(^hField.contains[minOccurs]){
					^if(!def $hData.[$sField].[$key]){
						$hData.[$sField].[$key][^hash::create[]]
					}
					$hTemp[$hData.[$sField].[$key]]
				}{
					$hTemp[$hData.[$sField]]
				}
				^self.getResponseFieldValue[$hTemp;$hWSDL;^value.getElementsByTagName[$key1];$hWSDL.types.[$sNS].ns;$key1;$value1]
			}
		}
	}{
		$iTemp(^hResponse._count[])
		$iNum(0)
		^hResponse.foreach[;value]{
			^if(def $value.childNodes.0.nodeValue || $value.childNodes.0.nodeType==1){
				^switch[$tField.1]{
					^case[boolean]{
						$Temp($value.childNodes.0.nodeValue eq "true")
					}
					^case[date]{
						$Temp[^formatDate[$value.childNodes.0.nodeValue;1;0]]
					}
					^case[dateTime]{
						$Temp[^formatDate[$value.childNodes.0.nodeValue;1]]
					}
					^case[decimal]{
						$Temp(^value.childNodes.0.nodeValue.format[%.2f])
					}
					^case[integer;int]{
						$Temp(^value.childNodes.0.nodeValue.int(0))
					}
					^case[string]{
						$Temp[$value.childNodes.0.nodeValue]
					}
					^case[Array]{
						$Temp[^hash::create[]]
						^if(^value.childNodes.0.hasChildNodes[]){
							^value.childNodes.0.childNodes.foreach[;value1]{
								^if(^value1.hasChildNodes[]){
									$hKey[^value1.getElementsByTagName[key]]
									$hValue[^value1.getElementsByTagName[value]]
									$Temp.[$hKey.0.childNodes.0.nodeValue][$hValue.0.childNodes.0.nodeValue]
								}
							}
						}
					}
				}
				^if(!^hField.contains[minOccurs]){
					^if($Temp is bool || $Temp is int || $Temp is double){
						$hData.[$sField]($Temp)
					}{
						$hData.[$sField][$Temp]
					}
				}{
					^iNum.inc[]
					^if($iNum==1){
						$hData.[$sField][^hash::create[]]
					}
					^if($Temp is bool || $Temp is int || $Temp is double){
						$hData.[$sField].[$iNum]($Temp)
					}{
						$hData.[$sField].[$iNum][$Temp]
					}
				}
			}
		}
	}
	$result[]
Использование:
Клиент:
	^use[soap.p]
#	user и password использовались для базовой авторизации
	$oSOAP[^SOAP::create[
		$.sUser[user]
		$.sPassword[password]
		$.sCharset[UTF-8]
	]]
#	есть возможность парсить WSDL на локальном диске или на удаленном ресурсе по ссылке
	$hWSDL[^oSOAP.parseWSDL[wsdl.xml;1;1]]
#	указываем название функции, которую надо вызвать, и "сторону" (клиент или сервер)
#	hRequest - структура с данными (хеш), которые надо передать серверу
	$sHTML[^oSOAP.getRequest[$hWSDL;название функции;$hRequest;client]]
#	посылаем серверу сформированный запрос и получаем ответ в виде хеша
	$hData[^oSOAP.sendRequest[
		$.hWSDL[$hWSDL]
		$.sOperation[название функции]
		$.sRequest[$sHTML]
	]]
Сервер:
	^use[soap.p]
#	user и password использовались для базовой авторизации
	$oSOAP[^SOAP::create[
		$.sUser[user]
		$.sPassword[password]
		$.sCharset[UTF-8]
	]]
#	есть возможность парсить WSDL на локальном диске или на удаленном ресурсе по ссылке
	$hWSDL[^oSOAP.parseWSDL[wsdl.xml;1;1]]
#	принимаем от клиента запрос и получаем хеш с данными для обработки
	$hData[^oSOAP.getResponse[$hWSDL;^taint[as-is][$request:body];server]]
#	формируем хеш для ответа
	$hRequest[
		$...[...]
	]
#	возвращаем результат клиенту в "понятном" ему виде
	$result[^oSOAP.getRequest[$hWSDL;название функции;$hRequest;server]]