Parser.swift 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /**
  2. * https://github.com/tadija/AEXML
  3. * Copyright (c) Marko Tadić 2014-2019
  4. * Licensed under the MIT license. See LICENSE file.
  5. */
  6. import Foundation
  7. #if canImport(FoundationXML)
  8. import FoundationXML
  9. #endif
  10. /// Simple wrapper around `Foundation.XMLParser`.
  11. internal class Parser: NSObject, XMLParserDelegate {
  12. // MARK: - Properties
  13. let document: Document
  14. let data: Data
  15. var currentParent: Element?
  16. var currentElement: Element?
  17. var currentValue = String()
  18. var parseError: Error?
  19. private lazy var parserSettings: Options.ParserSettings = {
  20. return document.options.parserSettings
  21. }()
  22. // MARK: - Lifecycle
  23. init(document: Document, data: Data) {
  24. self.document = document
  25. self.data = data
  26. currentParent = document
  27. super.init()
  28. }
  29. // MARK: - API
  30. func parse() throws {
  31. let parser = Foundation.XMLParser(data: data)
  32. parser.delegate = self
  33. parser.shouldProcessNamespaces = parserSettings.shouldProcessNamespaces
  34. parser.shouldReportNamespacePrefixes = parserSettings.shouldReportNamespacePrefixes
  35. parser.shouldResolveExternalEntities = parserSettings.shouldResolveExternalEntities
  36. let success = parser.parse()
  37. if !success {
  38. guard let error = parseError else { throw XMLError.parsingFailed }
  39. throw error
  40. }
  41. }
  42. // MARK: - XMLParserDelegate
  43. func parser(_ parser: Foundation.XMLParser,
  44. didStartElement elementName: String,
  45. namespaceURI: String?,
  46. qualifiedName qName: String?,
  47. attributes attributeDict: [String : String]) {
  48. currentValue = String()
  49. currentElement = currentParent?.addChild(name: elementName, attributes: attributeDict)
  50. currentParent = currentElement
  51. }
  52. func parser(_ parser: Foundation.XMLParser, foundCharacters string: String) {
  53. currentValue.append(string)
  54. currentElement?.value = currentValue.isEmpty ? nil : currentValue
  55. }
  56. func parser(_ parser: Foundation.XMLParser,
  57. didEndElement elementName: String,
  58. namespaceURI: String?,
  59. qualifiedName qName: String?) {
  60. if parserSettings.shouldTrimWhitespace {
  61. currentElement?.value = currentElement?.value?
  62. .trimmingCharacters(in: .whitespacesAndNewlines)
  63. }
  64. currentParent = currentParent?.parent
  65. currentElement = nil
  66. }
  67. func parser(_ parser: Foundation.XMLParser, parseErrorOccurred parseError: Error) {
  68. self.parseError = parseError
  69. }
  70. }