///|
pub struct SitemapEntry {
loc : String
lastmod : String
changefreq : String
priority : String
} derive(Debug, Eq)
///|
pub fn sitemap_urls(xml : String) -> Array[String] {
let urls : Array[String] = []
for entry in sitemap_entries(xml) {
urls.push(entry.loc)
}
urls
}
///|
pub fn sitemap_entries(xml : String) -> Array[SitemapEntry] {
let entries : Array[SitemapEntry] = []
let blocks = xml_blocks(xml, "url")
for block in blocks {
let loc = xml_tag_text(block, "loc")
if loc != "" {
entries.push({
loc,
lastmod: xml_tag_text(block, "lastmod"),
changefreq: xml_tag_text(block, "changefreq"),
priority: xml_tag_text(block, "priority"),
})
}
}
entries
}
///|
pub fn sitemap_index_locations(xml : String) -> Array[String] {
let urls : Array[String] = []
let blocks = xml_blocks(xml, "sitemap")
for block in blocks {
let loc = xml_tag_text(block, "loc")
if loc != "" {
urls.push(loc)
}
}
urls
}
///|
pub fn xml_blocks(xml : String, tag : String) -> Array[String] {
let blocks : Array[String] = []
let open = "<" + tag
let close = "" + tag + ">"
let mut current = xml
while true {
match current.find(open) {
Some(start) => {
let after_open = current.unsafe_substring(start~, end=current.length())
match after_open.find(">") {
Some(gt) => {
let body_start = gt + 1
let body_rest = after_open.unsafe_substring(
start=body_start,
end=after_open.length(),
)
match body_rest.find(close) {
Some(end) => {
blocks.push(body_rest.unsafe_substring(start=0, end~))
current = body_rest.unsafe_substring(
start=end + close.length(),
end=body_rest.length(),
)
continue
}
None => break
}
}
None => break
}
}
None => break
}
}
blocks
}
///|
pub fn xml_tag_text(xml : String, tag : String) -> String {
let open = "<" + tag
let close = "" + tag + ">"
match xml.find(open) {
Some(start) => {
let after_open = xml.unsafe_substring(start~, end=xml.length())
match after_open.find(">") {
Some(gt) => {
let body = after_open.unsafe_substring(
start=gt + 1,
end=after_open.length(),
)
match body.find(close) {
Some(end) =>
xml_unescape(trim_ascii(body.unsafe_substring(start=0, end~)))
None => ""
}
}
None => ""
}
}
None => ""
}
}
///|
pub fn xml_unescape(text : String) -> String {
text_replace(
text_replace(
text_replace(text_replace(text, "&", "&"), "<", "<"),
">",
">",
),
""",
"\"",
)
}
///|
pub fn text_replace(text : String, from : String, to : String) -> String {
if from == "" {
return text
}
let mut out = ""
let mut current = text
while true {
match current.find(from) {
Some(index) => {
out = out + current.unsafe_substring(start=0, end=index) + to
current = current.unsafe_substring(
start=index + from.length(),
end=current.length(),
)
continue
}
None => {
out = out + current
break
}
}
}
out
}
///|
pub fn sitemap_report(xml : String) -> String {
let entries = sitemap_entries(xml)
let indexes = sitemap_index_locations(xml)
"urls=" +
entries.length().to_string() +
"\nindexes=" +
indexes.length().to_string()
}