从 NSAttributedString 中提取 table
Extract table from NSAttributedString
假设我从文件 (html 或 rtf) 中读取了 NSAttributedString
,并且在那个文件中我清楚地看到几个 table .有没有办法提取那些 table 或至少找到对应于 table 的 NSRange
?如果我能以某种方式从 NSAttributedString
中提取(数组)NSTextTableBlock
、NSTextTable
或 NSTextBlock
,那将是理想的。但如果那不可能,那么至少应该有一种方法可以找到 table 单元格或类似内容的 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
}
}
}
我发现这个问题的解决方案有点天真,但它确实有效。您基本上遍历 NSAttributedString 中的所有字符,查询它们的属性,然后检查其中是否有带有 table.
的 NSParagraphStyle
这段代码从给定位置提取 NSTextTable 数组(记住 tables 可以嵌套)
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)
}
}
这可以帮助您收集所有 tables(嵌套的 tables 除外 - 为了也收集它们,您必须 运行 在每个函数中递归地执行此函数table):
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
}
}
假设我从文件 (html 或 rtf) 中读取了 NSAttributedString
,并且在那个文件中我清楚地看到几个 table .有没有办法提取那些 table 或至少找到对应于 table 的 NSRange
?如果我能以某种方式从 NSAttributedString
中提取(数组)NSTextTableBlock
、NSTextTable
或 NSTextBlock
,那将是理想的。但如果那不可能,那么至少应该有一种方法可以找到 table 单元格或类似内容的 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
}
}
}
我发现这个问题的解决方案有点天真,但它确实有效。您基本上遍历 NSAttributedString 中的所有字符,查询它们的属性,然后检查其中是否有带有 table.
的 NSParagraphStyle这段代码从给定位置提取 NSTextTable 数组(记住 tables 可以嵌套)
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)
}
}
这可以帮助您收集所有 tables(嵌套的 tables 除外 - 为了也收集它们,您必须 运行 在每个函数中递归地执行此函数table):
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
}
}