Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOSDC令和時代のXML処理を考える

coe
September 10, 2022

 iOSDC令和時代のXML処理を考える

令和時代のXML処理を考える 〜もしあなたが巨大なXMLと相見える(あいまみえる)ことになったら〜 iOSDC Japan 2022

coe

September 10, 2022
Tweet

More Decks by coe

Other Decks in Technology

Transcript

  1. 9*# 9.-*OUFSGBDF#VJMEFS <?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch"

    propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX"> <device id="retina5_9" orientation="portrait" appearance="light"/> <dependencies> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--Top View Controller--> <scene sceneID="s0d-6b-0kx"> <objects> <viewController id="Y6W-OH-hqX" customClass="TopViewController" customModule="WinkCamera" customModuleProvider="target" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="5EZ-qb-Rvc" customClass="PreviewView" customModule="WinkCamera" customModuleProvider="target"> <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <viewLayoutGuide key="safeArea" id="Yhj-UR-jNr"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/> </view> <connections> <outlet property="previewView" destination="5EZ-qb-Rvc" id="eQc-tb-WN6"/> <outlet property="winkControl" destination="eOh-BF-nHF" id="ueK-OC-EJQ"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> <customObject id="eOh-BF-nHF" customClass="WinkControl" customModule="WinkCamera" customModuleProvider="target"> <connections> <action selector="takePhoto:" destination="CVf-dU-zam" eventType="valueChanged" id="jmL-r1-JhV"/> </connections> </customObject> <exit id="CVf-dU-zam" userLabel="Exit" sceneMemberID="exit"/> </objects> <point key="canvasLocation" x="35" y="104"/> </scene> </scenes> <resources> <systemColor name="systemBackgroundColor"> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> </systemColor> </resources> </document> •
  2. %0.

  3. ࣮ࡍʹ࢖ͬͯΈΔ 9.-%PDVNFOU w 9.-%PDVNFOUΛ࢖ͬͯ ͷ9.-಺༰දࣔ let data = NSDataAsset(name: "Rss")!.data

    let doc = try! XMLDocument(data: data) text = doc.rootElement()? .elements(forName: "channel").first? .elements(forName: "title").first? .stringValue ?? "" print(text) // RSSͷλΠτϧදࣔ
  4. ࣮ࡍʹ࢖ͬͯΈΔ 9.-%PDVNFOU w 9.-%PDVNFOUΛ࢖ͬͯ ͷ9.-಺༰දࣔ w 9.-%PDVNFOU͕J04 Ͱ͸ϏϧυΤϥʔ let data

    = NSDataAsset(name: "Rss")!.data // Cannot find 'XMLDocument' in scope let doc = try! XMLDocument(data: data) text = doc.rootElement()? .elements(forName: "channel").first? .elements(forName: "title").first? .stringValue ?? "" print(text) // RSSͷλΠτϧදࣔ
  5. ࣮ࡍʹ࢖ͬͯΈΔ 9.-%PDVNFOU w 9.-%PDVNFOUΛ࢖ͬͯ ͷ9.-಺༰දࣔ w 9.-%PDVNFOU͕J04 Ͱ͸ϏϧυΤϥʔ w 9.-%PDVNFOU͸

    NBD04ͷΈͷରԠ let data = NSDataAsset(name: "Rss")!.data #if os(macOS) let doc = try! XMLDocument(data: data) text = doc.rootElement()? .elements(forName: "channel").first? .elements(forName: "title").first? .stringValue ?? "" #endif print(text) // RSSͷλΠτϧදࣔ
  6. MJCYNM 0CKFDUJWF$ NSURL* url; auto fileUrl = [[url absoluteString] UTF8String];

    auto document = xmlReadFile(fileUrl, NULL, XML_PARSE_HUGE); auto cur = xmlDocGetRootElement(document); if (xmlStrcmp(cur->name, (xmlChar *)"HealthData") != 0) { return @""; } cur = cur->children; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar*)”ExportDate"))) { auto value = xmlGetProp(cur, (xmlChar *)"value"); auto valueString = [NSString stringWithCString:(char*)value encoding:NSUTF8StringEncoding]; return valueString; // xmlͷग़ྗ೔෇औಘ } cur = cur->next; } return @"";
  7. MJCYNMʹΑΔಡΈࠐΈ ϔϧεέΞσʔλͷಡΈࠐΈ w ϔϧεέΞσʔλͷYNMϑ ΝΠϧΛಡΈࠐΈ w (͋Γ·͢ let url =

    Bundle.main.url(forResource: "export", withExtension: "xml")! let start = Date() // ಺෦ͰlibxmlΛ࢖ͬͯಡΈࠐΈ let obj = MyObject(url: url) text = obj.readText() let end = Date() print(start.distance(to: end)) print(text)
  8. MJCYNMʹΑΔಡΈࠐΈ ϔϧεέΞσʔλͷಡΈࠐΈ w ϔϧεέΞσʔλͷYNMϑ ΝΠϧΛಡΈࠐΈ w (͋Γ·͢ w ಡΈࠐΈ͢Δͷʹ ඵ͔͔Δ

    let url = Bundle.main.url(forResource: "export", withExtension: "xml")! let start = Date() // ಺෦ͰlibxmlΛ࢖ͬͯಡΈࠐΈ let obj = MyObject(url: url) text = obj.readText() let end = Date() print(start.distance(to: end)) //←35ඵ print(text)
  9. w 4"9 &WFOU%SJWFO9.-  w 9.-Λઌ಄͔ΒಡΈࠐΈɺಛ௃఺͕ݟ͔ͭΔͨͼʹΠϕϯτͱͯ͠ฦ͢ w 9.-1BSTFS w %0.

    5SFF#BTFE9.-  w 9.-ΛશͯಡΈࠐΜͰΦϒδΣΫτԽ͠ɺΦϒδΣΫτ͔Βඞཁͳσʔ λʹΞΫηε͢Δ w େྔͷϦιʔε͕ඞཁʹͳΔ w 9.-%PDVNFOU .BDͷΈ 9.-ॲཧͷछྨ Ұൠతͳ9.-ͷղੳ
  10. 9.-1BSTFSʹΑΔಡΈࠐΈ ϔϧεέΞσʔλͷಡΈࠐΈ w ϔϧεέΞσʔλͷYNMϑ ΝΠϧΛಡΈࠐΈ w (ͷYNMϑΝΠϧ let url =

    Bundle.main.url(forResource: "export", withExtension: "xml")! let start = Date() let parser = XMLParser(contentsOf: url)! // ඞཁͳ஋Λऔಘ͢ΔͨΊͷॲཧΛdelegateʹ࣮૷ parser.delegate = self parser.parse() let end = Date() print(text) print(start.distance(to: end))
  11. 9.-1BSTFSʹΑΔಡΈࠐΈ ϔϧεέΞσʔλͷಡΈࠐΈ w ϔϧεέΞσʔλͷYNMϑ ΝΠϧΛಡΈࠐΈ w (ͷYNMϑΝΠϧ w ඵͰඞཁͳςΩε τ͕औಘͰ͖Δ

    w ΠϕϯτΛ؂ࢹ͠ɺඞ ཁͳσʔλΛऔಘ͠ऴ ͑ͨΒૣظऴྃ͢Δ let url = Bundle.main.url(forResource: "export", withExtension: "xml")! let start = Date() let parser = XMLParser(contentsOf: url)! // ඞཁͳ஋Λऔಘ͢ΔͨΊͷॲཧΛdelegateʹ࣮૷ parser.delegate = self parser.parse() let end = Date() print(text) print(start.distance(to: end)) // ← 0.2ඵ
  12. 9.-1BSTFSʹΑΔಡΈࠐΈ ϔϧεέΞσʔλͷಡΈࠐΈ w ϔϧεέΞσʔλͷYNMϑ ΝΠϧΛಡΈࠐΈ w (ͷYNMϑΝΠϧ w ඵͰඞཁͳςΩε τ͕औಘͰ͖Δ

    w ΠϕϯτΛ؂ࢹ͠ɺඞ ཁͳσʔλΛऔಘ͠ऴ ͑ͨΒૣظऴྃ͢Δ // MARK: - XMLParserDelegate func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { // σʔλऔಘʹඞཁͳॲཧΛߦ͏ } func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { // ඞཁͳσʔλ͕औಘͰ͖ͨΒɺXMLParserΛૣظऴྃ parser.abortParsing() }
  13. 9.-1BSTFS खॱ w 9.-1BSTFSͷॳظԽ w %BUB w *OQVU4USFBN w 63-

    w 9.-1BSTFS%FMFHBUFΛઃఆͯ͠ ΠϕϯτΛड͚औΕΔΑ͏ʹ͢Δ w 9.-1BSTFSQBSTF Λ࣮ߦͯ͠ ֤छΠϕϯτΛEFMFHBUFͰॲཧ
  14. 9.-1BSTFS खॱ w 9.-1BSTFSͷॳظԽ w %BUB w *OQVU4USFBN w 63-

    w 9.-1BSTFS%FMFHBUFΛઃఆͯ͠ ΠϕϯτΛड͚औΕΔΑ͏ʹ͢Δ w 9.-1BSTFSQBSTF Λ࣮ߦͯ͠ ֤छΠϕϯτΛEFMFHBUFͰॲཧ let parser = XMLParser(contentsOf: url)! // ॳظԽ parser.delegate = self //delegateઃఆ parser.parse() // ॲཧ։࢝
  15. w 9.-1BSTFS%FMFHBUFQBSTFS @EJE4UBSU&MFNFOUOBNFTQBDF63*RV BMJ fi FE/BNFBUUSJCVUFT  w ཁૉ໊ͷ։͕࢝ݟ͔ͭͬͨ৔߹ʹݺͼग़͞ΕΔ w

    9.-1BSTFS%FMFHBUFQBSTFS @GPVOE$IBSBDUFST w ಺༰͕ݟ͔ͭͬͨ৔߹ʹݺͼग़͞ΕΔ w ҰճͰ͸಺༰͕શͯಡΈऔΕͣɺෳ਺ճݺ͹ΕΔ৔߹΋͋Δ w 9.-1BSTFS%FMFHBUFQBSTFS @EJE&OE&MFNFOUOBNFTQBDF63*RVBM J fi FE/BNF w ཁૉ໊ͷऴ͕ྃݟ͔ͭͬͨ৔߹ʹݺͼग़͞ΕΔ Α͘࢖͏GVOD 9.-1BSTFS%FMFHBUF
  16. ಺༰ͷऔಘ func parser(_ parser: XMLParser, foundCharacters string: String) { print(string)

    // ԕ͘ͰςϨϏͷిݯ͕ೖͬͨ͜ͱ͕Θ͔Δ } 9.-1BSTFS%FMFHBUF
  17. <ϓϩϑΟʔϧ> <໊લ>೔޲ڧ</໊લ> <ॴଐ>גࣜձࣾAmazia</ॴଐ> <աڈͷiOSDC> <λΠτϧ year="2019">BLEͰiOS/AndroidؒͰͦͦ͜͜େ͖ͳαΠζͷσʔλ௨৴Λ࣮ݱ͢Δ (L2CAP΋͋ΔΑ)</λΠτϧ> <λΠτϧ year="2020">ৄղStoryboard</λΠτϧ> <λΠτϧ

    year="2020">͋ͳͨͷ஌Βͳ͍࿈བྷઌͷੈք</λΠτϧ> <λΠτϧ year="2021">όοΫάϥ΢ϯυͰΞϓϦ͕Ωϧ͞Εͯ΋ා͘ͳ͍ʂΞϓϦͷঢ়ଶΛݩʹ໭͢ϦετΞػೳͷશͯ</λΠτϧ> </աڈͷiOSDC> <޷͖ͳ3DO>REAL</޷͖ͳ3DO> <ಛٕ>ԕ͘ͰςϨϏͷిݯ͕ೖͬͨ͜ͱ͕Θ͔Δ</ಛٕ> </ϓϩϑΟʔϧ>
  18. ಺༰ͷऔಘ func parser(_ parser: XMLParser, foundCharacters string: String) { print(string)

    // ೔޲ڧ // גࣜձࣾAmazia // BLEͰiOS/AndroidؒͰͦͦ͜͜େ͖ͳαΠζͷσʔλ௨৴Λ࣮ݱ͢Δ (L2CAP΋͋ΔΑ) // ৄղStoryboard // ͋ͳͨͷ஌Βͳ͍࿈བྷઌͷੈք // όοΫάϥ΢ϯυͰΞϓϦ͕Ωϧ͞Εͯ΋ා͘ͳ͍ʂΞϓϦͷঢ়ଶΛݩʹ໭͢ϦετΞػೳͷશͯ // REAL // ԕ͘ͰςϨϏͷిݯ͕ೖͬͨ͜ͱ͕Θ͔Δ } 9.-1BSTFS%FMFHBUF
  19. var isName = false func parser(_ parser: XMLParser, didStartElement elementName:

    String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { // ݱࡏղੳதͷλάΛ൑ఆ if elementName == "໊લ" { isName = true } } func parser(_ parser: XMLParser, foundCharacters string: String) { if isName { text.append(string) } } func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { // ղੳதϑϥάΛOFF if elementName == "໊લ" { isName = false } } 9.-1BSTFS%FMFHBUF ໊લΛऔಘ
  20. public func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?,

    qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { let child = ElementParser(parser: parser, elementName: elementName, attributeDict: attributeDict, parent: self, parentElement: element) childParser = child parser.delegate = child } 9.-1BSTFSͰ%0. 6TJOH.VMUJQMF%FMFHBUFT ։࢝λά͕ݟ͔ͭΔͨͼʹ৽ͨʹΦϒδΣΫτΛ࡞੒͠ɺEFMFHBUFͷର৅Λ੾Γସ͑Δ
  21. public func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?,

    qualifiedName qName: String?) { parentParser?.addChild(element) parser.delegate = parentParser } private func addChild(_ child: Element) { element.addElement(child) } 9.-1BSTFSͰ%0. 6TJOH.VMUJQMF%FMFHBUFT λά͕ऴྃͨ͠Β਌ΤϨϝϯτʹ௥Ճ
  22. let parser = ElementParser() let xmlParser = XMLParser(data: rss2XmlData) let

    rss2document: Element = parser.getDocument(from: xmlParser) 9.-1BSTFSͰ%0. 6TJOH.VMUJQMF%FMFHBUFT 344ͷ%0.Λऔಘ
  23. let parser = ElementParser() let xmlParser = XMLParser(data: rss2XmlData) let

    rss2document: Element = parser.getDocument(from: xmlParser) STTWFSTJPO DIBOOFM UJUMFχϡʔεɾτϐοΫεUJUMF  JUFN UJUMF5TVZPTIJIZVHBɺϝΨωΛ৽ௐUJUMF  JUFN DIBOOFM STT 9.-1BSTFSͰ%0. 6TJOH.VMUJQMF%FMFHBUFT STTEPDVNFOU͔ΒUJUMFΛऔಘ͢Δʹ͸ʁ
  24. @dynamicMemberLookup public class Element { private var _elements: [String: [Element]]

    public subscript(dynamicMember member: String) -> Element? { return _elements[member]?[0] } 6TJOH.VMUJQMF%FMFHBUFT !EZOBNJD.FNCFS-PPLVQ
  25. let parser = ElementParser() let xmlParser = XMLParser(data: rss2XmlData) let

    rss2document: Element = parser.getDocument(from: xmlParser) 6TJOH.VMUJQMF%FMFHBUFT !EZOBNJD.FNCFS-PPLVQ
  26. let parser = ElementParser() let xmlParser = XMLParser(data: rss2XmlData) let

    rss2document: Element = parser.getDocument(from: xmlParser) // χϡʔεɾτϐοΫε let channelTitle = rss2document.rss?.channel?.title?.getStringValue() // Tsuyoshi hyugaɺϝΨωΛ৽ௐ let itemTitle = rss2document.rss?.channel?.item?[0]?.title?.getStringValue() 6TJOH.VMUJQMF%FMFHBUFT !EZOBNJD.FNCFS-PPLVQ STTWFSTJPO DIBOOFM UJUMFχϡʔεɾτϐοΫεUJUMF  JUFN UJUMF5TVZPTIJIZVHBɺϝΨωΛ৽ௐUJUMF  JUFN DIBOOFM STT
  27. let atomData = atomXml.data(using: .utf8)! let parser = ElementParser() let

    xmlParser = XMLParser(data: atomData) let document: Element = parser.getDocument(from: xmlParser) let channelTitle = document.feed?.title?.getStringValue() let itemTitle = document.feed?.entry?[2]?.title?.getStringValue() document.feed?.entry?.getArrayValue()?.forEach({ _ in // ԿΒ͔ͷॲཧ }) 6TJOH.VMUJQMF%FMFHBUFT !EZOBNJD.FNCFS-PPLVQ "UPNGFFE
  28. let data = profileXml.data(using: .utf8)! let parser = ElementParser() let

    xmlParser = XMLParser(data: data) let document: Element = parser.getDocument(from: xmlParser) document.ϓϩϑΟʔϧ?.໊લ?.getStringValue() // ೔޲ڧ document.ϓϩϑΟʔϧ?.޷͖ͳ3DO?.getStringValue() // REAL document.ϓϩϑΟʔϧ?.ओͳ࣮੷?.getStringValue() // nil 6TJOH.VMUJQMF%FMFHBUFT !EZOBNJD.FNCFS-PPLVQ ϓϩϑΟʔϧ
  29. ໊લۭؒ 344 SEG3%'YNMOTIUUQQVSMPSHSTTYNMOTSEGIUUQXXXXPSHSEGTZOUBYOTYNMOTEDIUUQQVSMPSH EDFMFNFOUTYNMOTNOIUUQVTFGVMJODDPNSTTNBOJGFTUYNMMBOHKB DIBOOFM UJUMF೔هUJUMF ʜ DIBOOFM ʜ JUFNSEGBCPVUIUUQTFYBNQMFBSUJDMF

    UJUMFλΠτϧUJUMF MJOLIUUQTHJIZPKQFYBNQMFBSUJDMFMJOL EFTDSJQUJPOίϯςϯπͷઆ໌Ͱ͢EFTDSJQUJPO EDEBUF5 EDEBUF EDTVCKFDUϗοτϥΠϯEDTVCKFDU EDDSFBUPSUTVZPTIJIZVHBEDDSFBUPS JUFN SEG3%'
  30. ໊લۭؒ 344 SEG3%'YNMOTIUUQQVSMPSHSTTYNMOTSEGIUUQXXXXPSHSEGTZOUBYOTYNMOTEDIUUQ QVSMPSHEDFMFNFOUTYNMOTNOIUUQVTFGVMJODDPNSTTNBOJGFTUYNMMBOHKB DIBOOFM UJUMF೔هUJUMF ʜ DIBOOFM ʜ JUFNSEGBCPVUIUUQTFYBNQMFBSUJDMF

    UJUMFλΠτϧUJUMF MJOLIUUQTHJIZPKQFYBNQMFBSUJDMFMJOL EFTDSJQUJPOίϯςϯπͷઆ໌Ͱ͢EFTDSJQUJPO EDEBUF5 EDEBUF EDTVCKFDUϗοτϥΠϯEDTVCKFDU EDDSFBUPSUTVZPTIJIZVHBEDDSFBUPS JUFN SEG3%' EDͷ໊લۭؒఆٛ
  31. ໊લۭؒ 344 SEG3%'YNMOTIUUQQVSMPSHSTTYNMOTSEGIUUQXXXXPSHSEGTZOUBYOTYNMOTEDIUUQ QVSMPSHEDFMFNFOUTYNMOTNOIUUQVTFGVMJODDPNSTTNBOJGFTUYNMMBOHKB DIBOOFM UJUMF೔هUJUMF ʜ DIBOOFM ʜ JUFNSEGBCPVUIUUQTFYBNQMFBSUJDMF

    UJUMFλΠτϧUJUMF MJOLIUUQTHJIZPKQFYBNQMFBSUJDMFMJOL EFTDSJQUJPOίϯςϯπͷઆ໌Ͱ͢EFTDSJQUJPO EDEBUF5 EDEBUF EDTVCKFDUϗοτϥΠϯEDTVCKFDU EDDSFBUPSUTVZPTIJIZVHBEDDSFBUPS JUFN SEG3%' ໊લۭؒ63-EDʹଐ͢Δ
  32. w σϑΥϧτ͸GBMTF w USVFʹ͢Δͱɺ9.-1BSTFS%FMFHBUFͷҎԼͷGVODͷಈ࡞͕มΘ Δ w QBSTFS @EJE4UBSU&MFNFOUOBNFTQBDF63*RVBMJ fi FE/B

    NFBUUSJCVUFT w QBSTFS @EJE&OE&MFNFOUOBNFTQBDF63*RVBMJ fi FE/B NF TIPVME1SPDFTT/BNFTQBDFT ໊લۭؒ
  33. TIPVME1SPDFTT/BNFTQBDFT ໊લۭؒॲཧ '"-4& %FGBVMU 536& FMFNFOU/BNF EDEBUF EBUF OBNFTQBDF63* OJM

    IUUQQVSMPSHEDFMFNFOUT R/BNF OJM EDEBUF SEG3%'YNMOTIUUQQVSMPSHSTTYNMOTSEGIUUQXXXXPSHSEGTZOUBYOTYNMOTEDIUUQ QVSMPSHEDFMFNFOUTYNMOTNOIUUQVTFGVMJODDPNSTTNBOJGFTUYNMMBOHKB DIBOOFM UJUMF೔هUJUMF ʜ DIBOOFM ʜ JUFNSEGBCPVUIUUQTFYBNQMFBSUJDMF UJUMFλΠτϧUJUMF MJOLIUUQTHJIZPKQFYBNQMFBSUJDMFMJOL EFTDSJQUJPOίϯςϯπͷઆ໌Ͱ͢EFTDSJQUJPO EDEBUF5 EDEBUF EDTVCKFDUϗοτϥΠϯEDTVCKFDU EDDSFBUPSUTVZPTIJIZVHBEDDSFBUPS JUFN SEG3%'
  34. w σϑΥϧτ͸GBMTF w USVFʹ͢Δͱɺ9.-1BSTFS%FMFHBUFͰ৽ͨͳϝιου͕ίʔϧ ͞ΕΔΑ͏ʹͳΔ w QBSTFS @EJE4UBSU.BQQJOH1SF fi YUP63*

    w QBSTFS @EJE&OE.BQQJOH1SF fi Y  w ໊લۭؒఆٛΛಡΈࠐΜͩͱ͖ʹݺ͹ΕΔ TIPVME3FQPSU/BNFTQBDF1SF fi YFT ໊લۭؒ
  35. %5%

  36. %5%

  37. ϔϧεέΞͷ9.-%5%ൈਮ %5% %0$5:1&)FBMUI%BUB< )FBMUI,JU&YQPSU7FSTJPO &-&.&/5)FBMUI%BUB &YQPSU%BUF .F 3FDPSEc$PSSFMBUJPOc8PSLPVUc"DUJWJUZ4VNNBSZc$MJOJDBM3FDPSE  "55-*45)FBMUI%BUB

    MPDBMF$%"5"3&26*3&%  &-&.&/5&YQPSU%BUF&.15: "55-*45&YQPSU%BUF WBMVF$%"5"3&26*3&%  &-&.&/5.F&.15: "55-*45.F ),$IBSBDUFSJTUJD5ZQF*EFOUJ fi FS%BUF0G#JSUI$%"5"3&26*3&% ),$IBSBDUFSJTUJD5ZQF*EFOUJ fi FS#JPMPHJDBM4FY$%"5"3&26*3&% ),$IBSBDUFSJTUJD5ZQF*EFOUJ fi FS#MPPE5ZQF$%"5"3&26*3&% ),$IBSBDUFSJTUJD5ZQF*EFOUJ fi FS'JU[QBUSJDL4LJO5ZQF$%"5"3&26*3&%   >
  38. &-&.&/5"55-*45 %5% &-&.&/53FDPSE .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU  "55-*453FDPSE UZQF$%"5"3&26*3&% VOJU$%"5"*.1-*&% WBMVF$%"5"*.1-*&% TPVSDF/BNF$%"5"3&26*3&%

    TPVSDF7FSTJPO$%"5"*.1-*&% EFWJDF$%"5"*.1-*&% DSFBUJPO%BUF$%"5"*.1-*&% TUBSU%BUF$%"5"3&26*3&% FOE%BUF$%"5"3&26*3&% 
  39. &-&.&/5"55-*45 %5% &-&.&/53FDPSE .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU  "55-*453FDPSE UZQF$%"5"3&26*3&% VOJU$%"5"*.1-*&% WBMVF$%"5"*.1-*&% TPVSDF/BNF$%"5"3&26*3&%

    TPVSDF7FSTJPO$%"5"*.1-*&% EFWJDF$%"5"*.1-*&% DSFBUJPO%BUF$%"5"*.1-*&% TUBSU%BUF$%"5"3&26*3&% FOE%BUF$%"5"3&26*3&%  3FDPSEUZQF),2VBOUJUZ5ZQF*EFOUJ fi FS#MPPE(MVDPTFTPVSDF/BNFϔϧεέΞTPVSDF7FSTJPOVOJUNHE- DSFBUJPO%BUF TUBSU%BUF FOE%BUF WBMVF .FUBEBUB&OUSZLFZ),8BT6TFS&OUFSFEWBMVF 3FDPSE
  40. &-&.&/5 %5% &-&.&/53FDPSE .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU  "55-*453FDPSE UZQF$%"5"3&26*3&% VOJU$%"5"*.1-*&% WBMVF$%"5"*.1-*&% TPVSDF/BNF$%"5"3&26*3&%

    TPVSDF7FSTJPO$%"5"*.1-*&% EFWJDF$%"5"*.1-*&% DSFBUJPO%BUF$%"5"*.1-*&% TUBSU%BUF$%"5"3&26*3&% FOE%BUF$%"5"3&26*3&%  3FDPSEUZQF),2VBOUJUZ5ZQF*EFOUJ fi FS#MPPE(MVDPTFTPVSDF/BNFϔϧεέΞTPVSDF7FSTJPOVOJUNHE- DSFBUJPO%BUF TUBSU%BUF FOE%BUF WBMVF .FUBEBUB&OUSZLFZ),8BT6TFS&OUFSFEWBMVF 3FDPSE
  41. "55-*45 %5% &-&.&/53FDPSE .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU  "55-*453FDPSE UZQF$%"5"3&26*3&% VOJU$%"5"*.1-*&% WBMVF$%"5"*.1-*&% TPVSDF/BNF$%"5"3&26*3&%

    TPVSDF7FSTJPO$%"5"*.1-*&% EFWJDF$%"5"*.1-*&% DSFBUJPO%BUF$%"5"*.1-*&% TUBSU%BUF$%"5"3&26*3&% FOE%BUF$%"5"3&26*3&%  3FDPSEUZQF),2VBOUJUZ5ZQF*EFOUJ fi FS#MPPE(MVDPTFTPVSDF/BNFϔϧεέΞTPVSDF7FSTJPOVOJUNH E-DSFBUJPO%BUF TUBSU%BUF FOE%BUF  WBMVF .FUBEBUB&OUSZLFZ),8BT6TFS&OUFSFEWBMVF 3FDPSE
  42. optional func parser( _ parser: XMLParser, foundElementDeclarationWithName elementName: String, model:

    String ) &-&.&/5ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE&MFNFOU%FDMBSBUJPO8JUI/BNFNPEFM parser An NSXMLParser object parsing XML. elementName A string that is the name of an element. model A string that specifies a model for elementName.
  43. &-&.&/5ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE&MFNFOU%FDMBSBUJPO8JUI/BNFNPEFM parser An NSXMLParser object parsing XML. elementName

    A string that is the name of an element. model A string that specifies a model for elementName. &-&.&/53FDPSE .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU 
  44. &-&.&/5ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE&MFNFOU%FDMBSBUJPO8JUI/BNFNPEFM parser An NSXMLParser object parsing XML. elementName

    A string that is the name of an element. model A string that specifies a model for elementName. &-&.&/53FDPSE .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU 
  45. &-&.&/5ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE&MFNFOU%FDMBSBUJPO8JUI/BNFNPEFM parser An NSXMLParser object parsing XML. elementName

    A string that is the name of an element. model A string that specifies a model for elementName. &-&.&/53FDPSE .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU 
  46. optional func parser( _ parser: XMLParser, foundElementDeclarationWithName elementName: String, model:

    String ) &-&.&/5ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE&MFNFOU%FDMBSBUJPO8JUI/BNFNPEFM &-&.&/53FDPSE .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU  ༧૝ FMFNFOU/BNF 3FDPSE NPEFM .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU
  47. optional func parser( _ parser: XMLParser, foundElementDeclarationWithName elementName: String, model:

    String ) &-&.&/5ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE&MFNFOU%FDMBSBUJPO8JUI/BNFNPEFM &-&.&/53FDPSE .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU  ༧૝ ࣮ࡍ FMFNFOU/BNF 3FDPSE 3FDPSE NPEFM .FUBEBUB&OUSZc)FBSU3BUF7BSJBCJMJUZ.FUBEBUB-JTU ۭจࣈ
  48. optional func parser( _ parser: XMLParser, foundAttributeDeclarationWithName attributeName: String, forElement

    elementName: String, type: String?, defaultValue: String? ) "55-*45ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE"UUSJCVUF%FDMBSBUJPO8JUI/BNFGPS&MFNFOUUZQFEFGBVMU7B MVF  parser An NSXMLParser object parsing XML. attributeName A string that is the name of an attribute. elementName A string that is the name of an element that has the attribute attributeName. type A string, such as "ENTITY", "NOTATION", or "ID", that indicates the type of the attribute. defaultValue A string that specifies the default value of the attribute.
  49. "55-*45ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE"UUSJCVUF%FDMBSBUJPO8JUI/BNFGPS&MFNFOUUZQFEFGBVMU7B MVF  parser An NSXMLParser object parsing

    XML. attributeName A string that is the name of an attribute. elementName A string that is the name of an element that has the attribute attributeName. type A string, such as "ENTITY", "NOTATION", or "ID", that indicates the type of the attribute. defaultValue A string that specifies the default value of the attribute. "55-*45TRVBSFXJEUI$%"5"
  50. "55-*45ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE"UUSJCVUF%FDMBSBUJPO8JUI/BNFGPS&MFNFOUUZQFEFGBVMU7B MVF  parser An NSXMLParser object parsing

    XML. attributeName A string that is the name of an attribute. elementName A string that is the name of an element that has the attribute attributeName. type A string, such as "ENTITY", "NOTATION", or "ID", that indicates the type of the attribute. defaultValue A string that specifies the default value of the attribute. "55-*45TRVBSFXJEUI$%"5" ͭͷ஋͕ͦΕͧΕͷύϥϝʔλʹͳ͍ͬͯΔ
  51. "55-*45ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE"UUSJCVUF%FDMBSBUJPO8JUI/BNFGPS&MFNFOUUZQFEFGBVMU7B MVF  ༧૝ BUUSJCVUF/BNF XJEUI FMFNFOU/BNF TRVBSF

    UZQF $%"5" EFGBVMU7BMVF  optional func parser( _ parser: XMLParser, foundAttributeDeclarationWithName attributeName: String, forElement elementName: String, type: String?, defaultValue: String? ) "55-*45TRVBSFXJEUI$%"5"
  52. "55-*45ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE"UUSJCVUF%FDMBSBUJPO8JUI/BNFGPS&MFNFOUUZQFEFGBVMU7B MVF  ༧૝ ݁Ռ BUUSJCVUF/BNF XJEUI XJEUI

    FMFNFOU/BNF TRVBSF TRVBSF UZQF $%"5" ۭจࣈ EFGBVMU7BMVF   optional func parser( _ parser: XMLParser, foundAttributeDeclarationWithName attributeName: String, forElement elementName: String, type: String?, defaultValue: String? ) "55-*45TRVBSFXJEUI$%"5"
  53. "55-*45ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE"UUSJCVUF%FDMBSBUJPO8JUI/BNFGPS&MFNFOUUZQFEFGBVMU7B MVF  ༧૝ ࣮ࡍ BUUSJCVUF/BNF XJEUI XJEUI

    FMFNFOU/BNF TRVBSF TRVBSF UZQF $%"5" ۭจࣈ EFGBVMU7BMVF 3&26*3&% OJM optional func parser( _ parser: XMLParser, foundAttributeDeclarationWithName attributeName: String, forElement elementName: String, type: String?, defaultValue: String? ) "55-*45TRVBSFXJEUI$%"5"3&26*3&%
  54. ಺෦&/5*5: &/5*5:  YNMWFSTJPOFODPEJOH65'  %0$5:1&CPPLT< &/5*5:BVUIPSՆ໨ᕸੴ >  CPPLTOBNFॻ੶৘ใ

    CPPL UJUMFࡾ࢛࿠UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMFͦΕ͔ΒUJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMF໳UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPLT ಺෦&/5*5:Ͱஔ͖׵͑
  55. optional func parser( _ parser: XMLParser, foundInternalEntityDeclarationWithName name: String, value:

    String? ) ಺෦&/5*5:ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE*OUFSOBM&OUJUZ%FDMBSBUJPO8JUI/BNFWBMVF parser An NSXMLParser object parsing XML. name A string that is the declared name of an internal entity. value A string that is the value of entity name.
  56. ಺෦&/5*5:ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE*OUFSOBM&OUJUZ%FDMBSBUJPO8JUI/BNFWBMVF ༧૝ ࣮ࡍ OBNF BVUIPS BVUIPS WBMVF Ն໨ᕸੴ

    Ն໨ᕸੴ &/5*5:BVUIPSՆ໨ᕸੴ optional func parser( _ parser: XMLParser, foundInternalEntityDeclarationWithName name: String, value: String? )
  57. ಺෦&/5*5: &/5*5: func parser(_ parser: XMLParser, foundCharacters string: String) {

    print(string) } ಺༰͸Ͳ͏ग़ྗ͞ΕΔʁ CPPLTOBNFॻ੶৘ใ CPPL UJUMFࡾ࢛࿠UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMFͦΕ͔ΒUJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMF໳UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPLT
  58. ಺෦&/5*5: &/5*5: func parser(_ parser: XMLParser, foundCharacters string: String) {

    print(string) // Ն໨ᕸੴ } ಺༰͸Ͳ͏ग़ྗ͞ΕΔʁ CPPLTOBNFॻ੶৘ใ CPPL UJUMFࡾ࢛࿠UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMFͦΕ͔ΒUJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMF໳UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPLT
  59. ಺෦&/5*5: &/5*5: func parser(_ parser: XMLParser, foundCharacters string: String) {

    print(string) // &author; } ಺༰͸Ͳ͏ग़ྗ͞ΕΔʁ CPPLTOBNFॻ੶৘ใ CPPL UJUMFࡾ࢛࿠UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMFͦΕ͔ΒUJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMF໳UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPLT
  60. ಺෦&/5*5: &/5*5: func parser(_ parser: XMLParser, foundCharacters string: String) {

    print(string) // \n } վߦจࣈ͕͘Δˠม׵Ͱ͖ͳ͍ CPPLTOBNFॻ੶৘ใ CPPL UJUMFࡾ࢛࿠UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMFͦΕ͔ΒUJUMF BVUIPSBVUIPSBVUIPS CPPL CPPL UJUMF໳UJUMF BVUIPSBVUIPSBVUIPS CPPL CPPLT
  61. optional func parser( _ parser: XMLParser, foundExternalEntityDeclarationWithName name: String, publicID:

    String?, systemID: String? ) ֎෦&/5*5:ղੳ༻9.-1BSTFS%FMFHBUF QBSTFS @GPVOE&YUFSOBM&OUJUZ%FDMBSBUJPO8JUI/BNFQVCMJD*%TZTUFN*% 
  62. 9.-1BSTFSͰͷ֎෦&/5*5: &/5*5:  YNMWFSTJPOFODPEJOHVUG  %0$5:1&UFTU< &/5*5:FYUFSOBM4:45&.VTFS fi MFYNM >

    UFTUFYUFSOBMUFTU func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) { print(#function, #line, "parseError", parseError) } parser(_:parseErrorOccurred:) 45 parseError Error Domain=NSXMLParserErrorDomain Code=104 "(null)" UserInfo={NSXMLParserErrorColumn=17, NSXMLParserErrorLineNumber=5, NSXMLParserErrorMessage=Failure to process entity external }
  63. switch xmlParser.externalEntityResolvingPolicy { case .never: print("never") // ← Default case

    .noNetwork: print("noNetwork") case .sameOriginOnly: print("sameOriginOnly") case .always: print("always") @unknown default: print("default") } 9.-1BSTFSͰ%0. 6TJOH.VMUJQMF%FMFHBUFT σϑΥϧτͰ͸OFWFS͕ઃఆ͞Ε͍ͯΔ
  64. switch xmlParser.externalEntityResolvingPolicy { case .never: print("never") // ← Default case

    .noNetwork: print("noNetwork") case .sameOriginOnly: print("sameOriginOnly") case .always: print("always") @unknown default: print("default") } xmlParser.externalEntityResolvingPolicy = .noNetwork // or .always 9.-1BSTFSͰ%0. 6TJOH.VMUJQMF%FMFHBUFT ֎෦&OUJUZ͕ fi MFͷ৔߹ɺOP/FUXPSL΍BMXBZTʹઃఆ͢Δ
  65. 9.-1BSTFSͰͷ֎෦&/5*5: &/5*5:  YNMWFSTJPOFODPEJOHVUG  %0$5:1&UFTU< &/5*5:FYUFSOBM4:45&.VTFS fi MFYNM >

    UFTUFYUFSOBMUFTU JUFN UJUMFχϡʔελΠτϧUJUMF MJOLIUUQTFYBNQMFDPN MJOL QVC%BUF'SJ .BZ (.5QVC%BUF EFTDSJQUJPOχϡʔεهࣄ EFTDSJQUJPO DPNNFOUTIUUQT FYBNQMFDPNDPNNFOUT DPNNFOUT JUFN VTFS fi MFYNM
  66. 9.-1BSTFSͰͷ֎෦&/5*5: &/5*5:  YNMWFSTJPOFODPEJOHVUG  UFTU JUFN UJUMFχϡʔελΠτϧUJUMF MJOLIUUQTFYBNQMFDPNMJOL QVC%BUF'SJ

    .BZ (.5QVC%BUF EFTDSJQUJPOχϡʔεهࣄ EFTDSJQUJPO DPNNFOUTIUUQT FYBNQMFDPNDPNNFOUTDPNNFOUT JUFN UFTU JUFN UJUMFχϡʔελΠτϧUJUMF MJOLIUUQTFYBNQMFDPN MJOL QVC%BUF'SJ .BZ (.5QVC%BUF EFTDSJQUJPOχϡʔεهࣄ EFTDSJQUJPO DPNNFOUTIUUQT FYBNQMFDPNDPNNFOUT DPNNFOUT JUFN ֎෦ϑΝΠϧͷ಺༰ʹஔ͖׵ΘΔ VTFS fi MFYNM