Skip to content

Commit e3f093a

Browse files
committed
Initial Commit
0 parents  commit e3f093a

File tree

11 files changed

+273
-0
lines changed

11 files changed

+273
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
/.swiftpm

Package.resolved

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// swift-tools-version:5.1
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "XMLTV",
8+
products: [
9+
// Products define the executables and libraries produced by a package, and make them visible to other packages.
10+
.library(
11+
name: "XMLTV",
12+
targets: ["XMLTV"]),
13+
],
14+
dependencies: [
15+
// Dependencies declare other packages that this package depends on.
16+
// .package(url: /* package url */, from: "1.0.0"),
17+
.package(url: "https://github.com/Rubenfer/LightXMLParser.git", from: "0.1.0"),
18+
],
19+
targets: [
20+
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
21+
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
22+
.target(
23+
name: "XMLTV",
24+
dependencies: ["LightXMLParser"]),
25+
.testTarget(
26+
name: "XMLTVTests",
27+
dependencies: ["XMLTV"]),
28+
]
29+
)

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# XMLTV
2+
3+
XMLTV is a Swift package which allows you to parse XML files using the EPG XMLTV structure.
4+
5+
## Usage
6+
Add XMLTV to your project using Swift Package Manager.
7+
8+
XMLTV provides two structs representing channels and programs.
9+
10+
```swift
11+
public struct TVChannel {
12+
public let id: String
13+
public let name: String?
14+
public let url: String?
15+
public let icon: String?
16+
}
17+
18+
public struct TVProgram {
19+
public let start: Date?
20+
public let stop: Date?
21+
public let channel: TVChannel
22+
public let title: String?
23+
public let description: String?
24+
public let credits: [String:String]
25+
public let date: String?
26+
public let categories: [String]
27+
public let country: String?
28+
public let episode: String?
29+
public let icon: String?
30+
public let rating: String?
31+
}
32+
```
33+
34+
To parse files, you need to create an XMLTV object using the file data. Then you can use `getChannels() -> [TVChannel]` and `getPrograms(channel:) -> [TVProgram]` to get the information.

Sources/XMLTV/Date+XMLTV.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Foundation
2+
3+
extension Date {
4+
static func parse(tvDate: String?) -> Date? {
5+
guard let tvDate = tvDate else { return nil }
6+
let dateFormatter = DateFormatter()
7+
dateFormatter.dateFormat = "yyyyMMddHHmmss Z"
8+
return dateFormatter.date(from: tvDate)
9+
}
10+
}

Sources/XMLTV/TVChannel.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Foundation
2+
3+
public struct TVChannel {
4+
public let id: String
5+
public let name: String?
6+
public let url: String?
7+
public let icon: String?
8+
}

Sources/XMLTV/TVProgram.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import Foundation
2+
3+
public struct TVProgram {
4+
public let start: Date?
5+
public let stop: Date?
6+
public let channel: TVChannel
7+
public let title: String?
8+
public let description: String?
9+
public let credits: [String:String]
10+
public let date: String?
11+
public let categories: [String]
12+
public let country: String?
13+
public let episode: String?
14+
public let icon: String?
15+
public let rating: String?
16+
}
17+

Sources/XMLTV/XMLTV.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import Foundation
2+
import LightXMLParser
3+
4+
private extension XML {
5+
func children(name: String) -> [XML] {
6+
return children.filter { $0.name == name }
7+
}
8+
}
9+
10+
public class XMLTV {
11+
12+
private let xml: XML
13+
14+
public init(data: Data) {
15+
self.xml = XML(data: data)
16+
}
17+
18+
public func getChannels() -> [TVChannel] {
19+
var channels: [TVChannel] = []
20+
21+
let xmlChannels = xml.children(name: "channel")
22+
xmlChannels.forEach { channel in
23+
if let id = channel.attributes["id"] {
24+
let name = channel.children(name: "display-name").first?.value
25+
let url = channel.children(name: "url").first?.value
26+
let iconSrc = channel.children(name: "icon").first?.attributes["src"]
27+
channels.append(TVChannel(id: id, name: name, url: url, icon: iconSrc))
28+
}
29+
}
30+
31+
return channels
32+
}
33+
34+
public func getPrograms(channel: TVChannel) -> [TVProgram] {
35+
var programs: [TVProgram] = []
36+
37+
let xmlPrograms = xml.children.filter { $0.name == "programme" && $0.attributes["channel"] == channel.id }
38+
xmlPrograms.forEach { program in
39+
let startDate = Date.parse(tvDate: program.attributes["start"])
40+
let stopDate = Date.parse(tvDate: program.attributes["stop"])
41+
let title = program.children(name: "title").first?.value
42+
let description = program.children(name: "desc").first?.value
43+
let icon = program.children(name: "icon").first?.attributes["src"]
44+
let rating = program.children(name: "star-rating").first?.children(name: "value").first?.value
45+
let date = program.children(name: "date").first?.value
46+
let episode = program.children(name: "episode-num").first?.value
47+
let categories = program.children(name: "category").map { $0.value }
48+
let country = program.children(name: "country").first?.value
49+
let credits = program.children(name: "credits").first?.children.reduce([String:String]()) { dict, credit -> [String:String] in
50+
var dict = dict
51+
dict[credit.name] = credit.value
52+
return dict
53+
} ?? [:]
54+
programs.append(TVProgram(start: startDate, stop: stopDate, channel: channel, title: title, description: description, credits: credits, date: date, categories: categories, country: country, episode: episode, icon: icon, rating: rating))
55+
}
56+
57+
return programs
58+
}
59+
60+
}

Tests/LinuxMain.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import XCTest
2+
3+
import XMLTVTests
4+
5+
var tests = [XCTestCaseEntry]()
6+
tests += XMLTVTests.allTests()
7+
XCTMain(tests)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import XCTest
2+
3+
#if !canImport(ObjectiveC)
4+
public func allTests() -> [XCTestCaseEntry] {
5+
return [
6+
testCase(XMLTVTests.allTests),
7+
]
8+
}
9+
#endif

0 commit comments

Comments
 (0)