11/*
22 This source file is part of the Swift.org open source project
33
4- Copyright (c) 2022-2024 Apple Inc. and the Swift project authors
4+ Copyright (c) 2022 Apple Inc. and the Swift project authors
55 Licensed under Apache License v2.0 with Runtime Library Exception
66
77 See https://swift.org/LICENSE.txt for license information
1010
1111import Foundation
1212
13+ // On non-Darwin platforms, Foundation's XML support is vended as a separate module:
14+ // https://github.com/apple/swift-corelibs-foundation/blob/main/Docs/ReleaseNotes_Swift5.md#dependency-management
15+ #if canImport(FoundationXML)
16+ import FoundationXML
17+ #endif
18+
1319/// A basic XML parser that extracts the first `id` attribute found in the given SVG.
1420///
1521/// This is a single-purpose tool and should not be used for general-purpose SVG parsing.
@@ -19,19 +25,14 @@ enum SVGIDExtractor {
1925 /// Exposed for testing. The sibling `extractID(from: URL)` method is intended to be
2026 /// used within SwiftDocC.
2127 static func _extractID( from data: Data ) -> String ? {
22- // FIXME: Revert this and resume using XMLParser when rdar://138726860 is integrated into a Swift toolchain.
23- for capitalization in [ " id " , " ID " , " Id " , " iD " ] {
24- guard let idAttributeRange = data. firstRange ( of: Data ( " \( capitalization) = \" " . utf8) , in: data. indices) else {
25- continue
26- }
27-
28- guard let endQuote = data. firstRange ( of: Data ( " \" " . utf8) , in: idAttributeRange. upperBound... ) else {
29- continue
30- }
31-
32- return String ( data: data [ idAttributeRange. endIndex ..< endQuote. lowerBound] , encoding: . utf8)
33- }
34- return nil
28+ let delegate = SVGIDParserDelegate ( )
29+ let svgParser = XMLParser ( data: data)
30+ svgParser. delegate = delegate
31+
32+ // The delegate aborts the parsing when it finds the ID so the larger parsing operation is not "successful"
33+ _ = svgParser. parse ( )
34+
35+ return delegate. id
3536 }
3637
3738 /// Returns the first `id` attribute found in the given SVG, if any.
@@ -46,3 +47,22 @@ enum SVGIDExtractor {
4647 return _extractID ( from: data)
4748 }
4849}
50+
51+ private class SVGIDParserDelegate : NSObject , XMLParserDelegate {
52+ var id : String ?
53+
54+ func parser(
55+ _ parser: XMLParser ,
56+ didStartElement elementName: String ,
57+ namespaceURI: String ? ,
58+ qualifiedName qName: String ? ,
59+ attributes attributeDict: [ String : String ] = [ : ]
60+ ) {
61+ guard let id = attributeDict [ " id " ] ?? attributeDict [ " ID " ] ?? attributeDict [ " iD " ] ?? attributeDict [ " Id " ] else {
62+ return
63+ }
64+
65+ self . id = id
66+ parser. abortParsing ( )
67+ }
68+ }
0 commit comments