/ Sources / FoundationXML / XMLDTD.swift
XMLDTD.swift
  1  // This source file is part of the Swift.org open source project
  2  //
  3  // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
  4  // Licensed under Apache License v2.0 with Runtime Library Exception
  5  //
  6  // See http://swift.org/LICENSE.txt for license information
  7  // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  8  //
  9  
 10  #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
 11  import SwiftFoundation
 12  #else
 13  import Foundation
 14  #endif
 15  @_implementationOnly import CoreFoundation
 16  @_implementationOnly import CFXMLInterface
 17  
 18  /*!
 19      @class XMLDTD
 20      @abstract Defines the order, repetition, and allowable values for a document
 21  */
 22  open class XMLDTD : XMLNode {
 23  
 24      internal var _xmlDTD: _CFXMLDTDPtr {
 25          return _CFXMLDTDPtr(_xmlNode)
 26      }
 27      
 28      public init() {
 29          super.init(kind: .DTDKind, options: [])
 30      }
 31      
 32      public convenience init(contentsOf url: URL, options mask: XMLNode.Options = []) throws {
 33          setupXMLParsing()
 34          let urlString = url.absoluteString
 35  
 36          guard let node = _CFXMLParseDTD(urlString) else {
 37              //TODO: throw error
 38              fatalError("parsing dtd string failed")
 39          }
 40          self.init(ptr: node)
 41      }
 42  
 43      public convenience init(data: Data, options mask: XMLNode.Options = []) throws {
 44          setupXMLParsing()
 45          var unmanagedError: Unmanaged<CFError>? = nil
 46          
 47          guard let node = _CFXMLParseDTDFromData(unsafeBitCast(data as NSData, to: CFData.self), &unmanagedError) else {
 48              if let error = unmanagedError?.takeRetainedValue() {
 49                  throw _CFErrorSPIForFoundationXMLUseOnly(unsafelyAssumingIsCFError: error)._nsObject
 50              }
 51              //TODO: throw a generic error?
 52              fatalError("parsing dtd from data failed")
 53          }
 54          
 55          // _CFXMLParseDTDFromData assigns "none" to DTD's name when there's no name for DTD.
 56          if _CFXMLNodeNameEqual(node, "none") {
 57              _CFXMLNodeForceSetName(node, nil)
 58          }
 59          
 60          self.init(ptr: node)
 61      }
 62      
 63      /*!
 64          @method openID
 65          @abstract Sets the open id. This identifier should be in the default catalog in /etc/xml/catalog or in a path specified by the environment variable XML_CATALOG_FILES. When the public id is set the system id must also be set.
 66      */
 67      open var publicID: String? {
 68          get {
 69              let returned = _CFXMLDTDCopyExternalID(_xmlDTD)
 70              return returned == nil ? nil : unsafeBitCast(returned!, to: NSString.self) as String
 71          }
 72  
 73          set {
 74              if let value = newValue {
 75                  _CFXMLDTDSetExternalID(_xmlDTD, value)
 76              } else {
 77                  _CFXMLDTDSetExternalID(_xmlDTD, nil)
 78              }
 79          }
 80      }
 81      
 82      /*!
 83          @method systemID
 84          @abstract Sets the system id. This should be a URL that points to a valid DTD.
 85      */
 86      open var systemID: String? {
 87          get {
 88              let returned = _CFXMLDTDCopySystemID(_xmlDTD)
 89              return returned == nil ? nil : unsafeBitCast(returned!, to: NSString.self) as String
 90          }
 91  
 92          set {
 93              if let value = newValue {
 94                  _CFXMLDTDSetSystemID(_xmlDTD, value)
 95              } else {
 96                  _CFXMLDTDSetSystemID(_xmlDTD, nil)
 97              }
 98          }
 99      }
100  
101      open override var childCount: Int {
102          return _CFXMLNodeGetElementChildCount(_xmlNode)
103      }
104      
105      /*!
106          @method insertChild:atIndex:
107          @abstract Inserts a child at a particular index.
108      */
109      open func insertChild(_ child: XMLNode, at index: Int) {
110          _insertChild(child, atIndex: index)
111      } //primitive
112      
113      /*!
114          @method insertChildren:atIndex:
115          @abstract Insert several children at a particular index.
116      */
117      open func insertChildren(_ children: [XMLNode], at index: Int) {
118          _insertChildren(children, atIndex: index)
119      }
120      
121      /*!
122          @method removeChildAtIndex:
123          @abstract Removes a child at a particular index.
124      */
125      open func removeChild(at index: Int) {
126          _removeChildAtIndex(index)
127      } //primitive
128      
129      /*!
130          @method setChildren:
131          @abstract Removes all existing children and replaces them with the new children. Set children to nil to simply remove all children.
132      */
133      open func setChildren(_ children: [XMLNode]?) {
134          _setChildren(children)
135      } //primitive
136      
137      /*!
138          @method addChild:
139          @abstract Adds a child to the end of the existing children.
140      */
141      open func addChild(_ child: XMLNode) {
142          _addChild(child)
143      }
144      
145      /*!
146          @method replaceChildAtIndex:withNode:
147          @abstract Replaces a child at a particular index with another child.
148      */
149      open func replaceChild(at index: Int, with node: XMLNode) {
150          _replaceChildAtIndex(index, withNode: node)
151      }
152      
153      /*!
154          @method entityDeclarationForName:
155          @abstract Returns the entity declaration matching this name.
156      */
157      open func entityDeclaration(forName name: String) -> XMLDTDNode? {
158          guard let node = _CFXMLDTDGetEntityDesc(_xmlDTD, name) else { return nil }
159          return XMLDTDNode._objectNodeForNode(node)
160      } //primitive
161      
162      /*!
163          @method notationDeclarationForName:
164          @abstract Returns the notation declaration matching this name.
165      */
166      open func notationDeclaration(forName name: String) -> XMLDTDNode? {
167          guard let node = _CFXMLDTDGetNotationDesc(_xmlDTD, name) else { return nil }
168          return XMLDTDNode._objectNodeForNode(node)
169      } //primitive
170      
171      /*!
172          @method elementDeclarationForName:
173          @abstract Returns the element declaration matching this name.
174      */
175      open func elementDeclaration(forName name: String) -> XMLDTDNode? {
176          guard let node = _CFXMLDTDGetElementDesc(_xmlDTD, name) else { return nil }
177          return XMLDTDNode._objectNodeForNode(node)
178      } //primitive
179      
180      /*!
181          @method attributeDeclarationForName:
182          @abstract Returns the attribute declaration matching this name.
183      */
184      open func attributeDeclaration(forName name: String, elementName: String) -> XMLDTDNode? {
185          guard let node = _CFXMLDTDGetAttributeDesc(_xmlDTD, elementName, name) else { return nil }
186          return XMLDTDNode._objectNodeForNode(node)
187      } //primitive
188      
189      /*!
190          @method predefinedEntityDeclarationForName:
191          @abstract Returns the predefined entity declaration matching this name.
192      	@discussion The five predefined entities are
193      	<ul><li>&amp;lt; - &lt;</li><li>&amp;gt; - &gt;</li><li>&amp;amp; - &amp;</li><li>&amp;quot; - &quot;</li><li>&amp;apos; - &amp;</li></ul>
194      */
195      open class func predefinedEntityDeclaration(forName name: String) -> XMLDTDNode? {
196          guard let node = _CFXMLDTDGetPredefinedEntity(name) else { return nil }
197          return XMLDTDNode._objectNodeForNode(node)
198      }
199      
200      internal override class func _objectNodeForNode(_ node: _CFXMLNodePtr) -> XMLDTD {
201          precondition(_CFXMLNodeGetType(node) == _kCFXMLTypeDTD)
202  
203          if let privateData = _CFXMLNodeGetPrivateData(node) {
204              return unsafeBitCast(privateData, to: XMLDTD.self)
205          }
206          
207          return XMLDTD(ptr: node)
208      }
209      
210      internal override init(ptr: _CFXMLNodePtr) {
211          super.init(ptr: ptr)
212      }
213  }
214  
215