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>&lt; - <</li><li>&gt; - ></li><li>&amp; - &</li><li>&quot; - "</li><li>&apos; - &</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