我是在向soap API发送请求并从中提取数据的新手。我想知道如何解析Soap响应中的Json数据:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>[{"nationalid":"2135199186","countrylist":[{"countryCode":"AFG","CountryName":"Afghanistan"},{"countryCode":"DZA","CountryName":"Algeria"},{"countryCode":"BHR","CountryName":"Bahrain"},{"countryCode":"COM","CountryName":"Comoros"},{"countryCode":"DJI","CountryName":"Djibouti"},{"countryCode":"EGY","CountryName":"Egypt"},{"countryCode":"ERI","CountryName":"Eritrea"},{"countryCode":"IRQ","CountryName":"Iraq"},{"countryCode":"JOR","CountryName":"Jordan"},{"countryCode":"KWT","CountryName":"Kuwait"},{"countryCode":"LBN","CountryName":"Lebanon"},{"countryCode":"LBY","CountryName":"Libyan Arab Jamahiriya"},{"countryCode":"MRT","CountryName":"Mauritania"},{"countryCode":"MAR","CountryName":"Morocco"},{"countryCode":"OMN","CountryName":"Oman"},{"countryCode":"PAK","CountryName":"Pakistan"},{"countryCode":"PSE","CountryName":"Palestinian Territory, Occupie"},{"countryCode":"QAT","CountryName":"Qatar"},{"countryCode":"SOM","CountryName":"Somalia"},{"countryCode":"SDN","CountryName":"Sudan"},{"countryCode":"SYR","CountryName":"Syrian Arab Republic"},{"countryCode":"TUN","CountryName":"Tunisia"},{"countryCode":"ARE","CountryName":"United Arab Emirates"},{"countryCode":"YEM","CountryName":"Yemen"}],"isError":false}]</soapenv:Body>
</soapenv:Envelope>
修改
请求数据包如下所示:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:name="http://www.example.org/Name">
<soapenv:Header><wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>UODA_GUEST</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">@password123</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<Name>
<NATIONAL_ID>2135199186</NATIONAL_ID>
<SEC_KEY>1adb445f8815e450b25addad899cab156e63088c</SEC_KEY>
<LANG_CODE>ENG</LANG_CODE>
<SEC_CODE>@password123</SEC_CODE>
</Name>
</soapenv:Body>
</soapenv:Envelope>
响应如下:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>[{"nationalid":"2135199186","countrylist":[{"countryCode":"AFG","CountryName":"Afghanistan"},{"countryCode":"DZA","CountryName":"Algeria"},{"countryCode":"BHR","CountryName":"Bahrain"},{"countryCode":"COM","CountryName":"Comoros"},{"countryCode":"DJI","CountryName":"Djibouti"},{"countryCode":"EGY","CountryName":"Egypt"},{"countryCode":"ERI","CountryName":"Eritrea"},{"countryCode":"IRQ","CountryName":"Iraq"},{"countryCode":"JOR","CountryName":"Jordan"},{"countryCode":"KWT","CountryName":"Kuwait"},{"countryCode":"LBN","CountryName":"Lebanon"},{"countryCode":"LBY","CountryName":"Libyan Arab Jamahiriya"},{"countryCode":"MRT","CountryName":"Mauritania"},{"countryCode":"MAR","CountryName":"Morocco"},{"countryCode":"OMN","CountryName":"Oman"},{"countryCode":"PAK","CountryName":"Pakistan"},{"countryCode":"PSE","CountryName":"Palestinian Territory, Occupie"},{"countryCode":"QAT","CountryName":"Qatar"},{"countryCode":"SOM","CountryName":"Somalia"},{"countryCode":"SDN","CountryName":"Sudan"},{"countryCode":"SYR","CountryName":"Syrian Arab Republic"},{"countryCode":"TUN","CountryName":"Tunisia"},{"countryCode":"ARE","CountryName":"United Arab Emirates"},{"countryCode":"YEM","CountryName":"Yemen"}],"isError":false}]</soapenv:Body>
</soapenv:Envelope>
我正在创建这样的请求:
static func createServiceRequest(params : Dictionary<String,String>, serviceName:String, urlString: String, method: String) -> URLRequest {
var parameters : String = ""
for (key, param) in params {
parameters = "\(parameters)<\(key)>\(param)</\(key)>"
}
let soapMessage = "<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body><\(serviceName) xmlns=\"http://ud.edu.sa/api/ldap\">\(parameters)</\(serviceName)></Body></Envelope>"
let soapLenth = String(soapMessage.count)
let theURL = URL(string: urlString)
var mutableR = URLRequest(url: theURL!)
// MUTABLE REQUEST
mutableR.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
mutableR.addValue("text/html; charset=utf-8", forHTTPHeaderField: "Content-Type")
mutableR.addValue(soapLenth, forHTTPHeaderField: "Content-Length")
mutableR.httpMethod = method
mutableR.httpBody = soapMessage.data(using: String.Encoding.utf8)
return mutableR
}
}
然后创建一个url会话并使用Stimorol的XMLElementExtractor类:
func fetchJsonFor(request: URLRequest, completion: @escaping ((Any?) -> Void)){
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil{
print(error?.localizedDescription ?? "Error")
completion(nil)
}
guard let data = data else{
completion(nil)
return
}
let jsonString = XMLElementExtractor.extractElement("soapenv:Body", fromXML: data) ?? "NO JSON STRING"
print("JSON STRING:")
print(jsonString)
}
task.resume()
}
但是jsonString = 1
我得到的jsonString没有显示任何内容修改
print(String(data: data, encoding: .utf8) ?? "NO UTF8 DATA")
将在此屏幕截图中打印文本:
显然,我需要执行额外的步骤来执行此行
<wsdl:operation name="U_COUNTRYLIST"
因为当我点击屏幕截图顶角的U_COUNTRYLIST按钮时,会出现另一个屏幕。然后,当我将整个请求数据包粘贴到该屏幕时,我得到了包含所需json的结束肥皂响应。
答案 0 :(得分:0)
您可以使用此XML解析像这样AEXML
请检查此
print(String(describing: xmlDoc.root["soapenv:Body"].value))
这是代码
import UIKit
import AEXML
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// example from README.md
guard
let xmlPath = Bundle.main.path(forResource: "example", ofType: "xml"),
let data = try? Data(contentsOf: URL(fileURLWithPath: xmlPath))
else {
print("resource not found!")
return
}
// example of using NSXMLParserOptions
var options = AEXMLOptions()
options.parserSettings.shouldProcessNamespaces = false
options.parserSettings.shouldReportNamespacePrefixes = false
options.parserSettings.shouldResolveExternalEntities = false
do {
let xmlDoc = try AEXMLDocument(xml: data, options: options)
// prints the same XML structure as original
print(xmlDoc.xml)
// prints cats, dogs
for child in xmlDoc.root.children {
print(child.name)
}
print(String(describing: xmlDoc.root["soapenv:Body"].value)) // Print your REsponse
}
catch {
print("\(error)")
}
}
}
答案 1 :(得分:0)
如果您不想要外部依赖项,并且您需要的唯一XML元素是Body
,那么您可以为此创建简单的解析器:
import Foundation
final class XMLElementExtractor: NSObject, XMLParserDelegate {
private var isTarget = false
private var value: String?
private let elementName: String
private init(elementName: String) {
self.elementName = elementName
}
static func extractElement(_ elementName: String, fromXML data: Data) -> String? {
let extractor = XMLElementExtractor(elementName: elementName)
let parser = XMLParser(data: data)
parser.delegate = extractor
parser.parse()
return extractor.value
}
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
isTarget = elementName == self.elementName
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if isTarget {
value = value?.appending(string) ?? string
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if elementName == self.elementName {
parser.abortParsing()
}
}
}
let jsonString = XMLElementExtractor.extractElement("soapenv:Body", fromXML: data)
然后使用Codable
或JSONSerialization
解析返回的字符串。