// // Elements.swift // SwiftSoup // // Created by Nabil Chatbi on 20/10/16. // Copyright © 2016 Nabil Chatbi.. All rights reserved. // /** A list of {@link Element}s, with methods that act on every element in the list.
To get an {@code Elements} object, use the {@link Element#select(String)} method.
*/ import Foundation //open typealias Elements = Array
* Note that it is possible to get repeats if the matched elements contain both parent elements and their own
* children, as the Element.text() method returns the combined text of a parent and all its children.
* @return string of all text: unescaped and no HTML.
* @see Element#text()
*/
open func text()throws->String {
let sb: StringBuilder = StringBuilder()
for element: Element in this {
if (sb.length != 0) {
sb.append(" ")
}
sb.append(try element.text())
}
return sb.toString()
}
/// Check if an element has text
open func hasText() -> Bool {
for element: Element in this {
if (element.hasText()) {
return true
}
}
return false
}
/**
* Get the combined inner HTML of all matched elements.
* @return string of all element's inner HTML.
* @see #text()
* @see #outerHtml()
*/
open func html()throws->String {
var text = try this.reduce("") {result, name in "\(result)\(try name.html())\n"}
text.removeLast()
return text
}
/**
* Get the combined outer HTML of all matched elements.
* @return string of all element's outer HTML.
* @see #text()
* @see #html()
*/
open func outerHtml()throws->String {
let sb: StringBuilder = StringBuilder()
for element in this {
if (sb.length != 0) {
sb.append("\n")
}
sb.append(try element.outerHtml())
}
return sb.toString()
}
/**
* Get the combined outer HTML of all matched elements. Alias of {@link #outerHtml()}.
* @return string of all element's outer HTML.
* @see #text()
* @see #html()
*/
open func toString()throws->String {
return try outerHtml()
}
/**
* Update the tag name of each matched element. For example, to change each {@code } to a {@code }, do
* {@code doc.select("i").tagName("em");}
* @param tagName the new tag name
* @return this, for chaining
* @see Element#tagName(String)
*/
@discardableResult
open func tagName(_ tagName: String)throws->Elements {
for element: Element in this {
try element.tagName(tagName)
}
return self
}
/**
* Set the inner HTML of each matched element.
* @param html HTML to parse and set into each matched element.
* @return this, for chaining
* @see Element#html(String)
*/
@discardableResult
open func html(_ html: String)throws->Elements {
for element: Element in this {
try element.html(html)
}
return self
}
/**
* Add the supplied HTML to the start of each matched element's inner HTML.
* @param html HTML to add inside each element, before the existing HTML
* @return this, for chaining
* @see Element#prepend(String)
*/
@discardableResult
open func prepend(_ html: String)throws->Elements {
for element: Element in this {
try element.prepend(html)
}
return self
}
/**
* Add the supplied HTML to the end of each matched element's inner HTML.
* @param html HTML to add inside each element, after the existing HTML
* @return this, for chaining
* @see Element#append(String)
*/
@discardableResult
open func append(_ html: String)throws->Elements {
for element: Element in this {
try element.append(html)
}
return self
}
/**
* Insert the supplied HTML before each matched element's outer HTML.
* @param html HTML to insert before each element
* @return this, for chaining
* @see Element#before(String)
*/
@discardableResult
open func before(_ html: String)throws->Elements {
for element: Element in this {
try element.before(html)
}
return self
}
/**
* Insert the supplied HTML after each matched element's outer HTML.
* @param html HTML to insert after each element
* @return this, for chaining
* @see Element#after(String)
*/
@discardableResult
open func after(_ html: String)throws->Elements {
for element: Element in this {
try element.after(html)
}
return self
}
/**
Wrap the supplied HTML around each matched elements. For example, with HTML
{@code This is Jsoup This is jsoup
* This is useful for e.g removing unwanted formatting elements but keeping their contents.
* {@code doc.select("b").wrap("<i></i>");
becomes {@code
{@code doc.select("font").unwrap();}
*HTML = {@code
* E.g. HTML: {@code
Hello there
now
doc.select("p").empty();
* E.g. HTML: {@code
Hello
there
doc.select("p").remove();
* Note that this method should not be used to clean user-submitted HTML; rather, use {@link org.jsoup.safety.Cleaner} to clean HTML. * @return this, for chaining * @see Element#empty() * @see #empty() */ @discardableResult open func remove()throws->Elements { for element in this { try element.remove() } return self } // filters /** * Find matching elements within this element list. * @param query A {@link Selector} query * @return the filtered list of elements, or an empty list if none match. */ open func select(_ query: String)throws->Elements { return try Selector.select(query, this) } /** * Remove elements from this list that match the {@link Selector} query. *
* E.g. HTML: {@code
Elements divs = doc.select("div").not(".logo");
* @param query the selector query whose results should be removed from these elements * @return a new elements list that contains only the filtered results */ open func not(_ query: String)throws->Elements { let out: Elements = try Selector.select(query, this) return Selector.filterOut(this, out.this) } /** * Get the nth matched element as an Elements object. *
* See also {@link #get(int)} to retrieve an Element.
* @param index the (zero-based) index of the element in the list to retain
* @return Elements containing only the specified element, or, if that element did not exist, an empty list.
*/
open func eq(_ index: Int) -> Elements {
return size() > index ? Elements([get(index)]) : Elements()
}
/**
* Test if any of the matched elements match the supplied query.
* @param query A selector
* @return true if at least one element in the list matches the query.
*/
open func iS(_ query: String)throws->Bool {
let eval: Evaluator = try QueryParser.parse(query)
for e: Element in this {
if (try e.iS(eval)) {
return true
}
}
return false
}
/**
* Get all of the parents and ancestor elements of the matched elements.
* @return all of the parents and ancestor elements of the matched elements
*/
open func parents() -> Elements {
let combo: OrderedSetnull
if contents is empty.
*/
open func first() -> Element? {
return isEmpty() ? nil : get(0)
}
/// Check if no element stored
open func isEmpty() -> Bool {
return array().count == 0
}
/// Count
open func size() -> Int {
return array().count
}
/**
Get the last matched element.
@return The last matched element, or null
if contents is empty.
*/
open func last() -> Element? {
return isEmpty() ? nil : get(size() - 1)
}
/**
* Perform a depth-first traversal on each of the selected elements.
* @param nodeVisitor the visitor callbacks to perform on each node
* @return this, for chaining
*/
@discardableResult
open func traverse(_ nodeVisitor: NodeVisitor)throws->Elements {
let traversor: NodeTraversor = NodeTraversor(nodeVisitor)
for el: Element in this {
try traversor.traverse(el)
}
return self
}
/**
* Get the {@link FormElement} forms from the selected elements, if any.
* @return a list of {@link FormElement}s pulled from the matched elements. The list will be empty if the elements contain
* no forms.
*/
open func forms()->Array