Извлечь таблицу из NSAttributedString - PullRequest
0 голосов
/ 20 мая 2018

Предположим, я прочитал NSAttributedString из файла (html или rtf) и в этом файле я отчетливо вижу несколько таблиц.Есть ли способ извлечь эти таблицы или хотя бы найти NSRange, который соответствует таблице?Было бы идеально, если бы я мог как-то извлечь (массив) NSTextTableBlock, NSTextTable или NSTextBlock из NSAttributedString.Но если это невозможно, то, по крайней мере, должен быть способ найти NSRanges ячеек таблицы или что-то подобное.Swift (возможно, 4) предпочтительнее, но obj-c тоже подойдет.

Например, представьте такой сценарий:

let html =
"""
<table style="height: 51px;" width="147">
    <tbody>
        <tr>
            <td style="width: 65.5px;">a</td>
            <td style="width: 65.5px;">b</td>
        </tr>
        <tr>
            <td style="width: 65.5px;">c</td>
            <td style="width: 65.5px;">d</td>
        </tr>
    </tbody>
</table>
"""
var str = NSAttributedString(html: html.data(using: .utf8)!,    options: [:], documentAttributes: nil)!

, и тогда я хотел бы сделать что-то более или менее подобное:

for table in str{
    for row in table{
        for cell in row{
            //do something
        }
    }
}

1 Ответ

0 голосов
/ 21 мая 2018

Я нашел немного наивное решение этой проблемы, но оно работает.Вы в основном перебираете все символы в NSAttributedString, запрашиваете их атрибуты и затем проверяете, является ли среди них NSParagraphStyle с таблицей.

Этот фрагмент кода извлекает массив NSTextTable из заданного местоположения (помните, что таблицы могут быть вложенными)

extension NSAttributedString{

func paragraphStyle(at index:Int)->NSParagraphStyle?{
    let key = NSAttributedStringKey.paragraphStyle
    return attribute(key, at: index, effectiveRange: nil) as! NSParagraphStyle?
}
func textBlocks(at index:Int)->[NSTextBlock]?{
    return paragraphStyle(at: index)?.textBlocks
}
func tables(at index:Int)->[NSTextTable]?{
    guard let tbs = textBlocks(at: index) else{
        return nil
    }
    var output = Set<NSTextTable>()
    for tb in tbs{
        if let t = tb as? NSTextTableBlock{
            output.insert(t.table)
        }
    }
    return Array(output)
}

}

И это может помочь вам собрать все таблицы (кроме вложенных таблиц - для того, чтобы собирать их тоже, вам придется рекурсивно запускать эту функцию внутри каждой таблицы):

extension NSAttributedString{

var outterTables:[NSTextTable]{
    var index = 0
    let len = length
    var output:[NSTextTable] = []
    while index < len{
        if let tab = outterTable(at: index){
            output.append(tab)
            index = range(of: tab, at: index).upperBound
        }else{
            index += 1
        }
    }
    return output
}

}
...