HTML 解析指南
使用下面列出的组、属性和其他 XML 属性解析 VuSitu 或 HydroVu HTML 文件。 使用本页底部用 Python 编写的示例解析器作为您自己的脚本的模型,或自定义代码以满足您的需求。 我们还提供了几个您可以用于测试的 VuSitu HTML 文件。
组别
位置属性
报告属性
仪器属性
记录属性
测试属性
井属性
泵属性
管道属性
位置属性
名称
全局唯一标识符
纬度
经度
报告属性
起始时间
创建者
时长
读数
时间偏差
仪器属性
型号
序列号
固件版本
记录属性
记录类型
名称
全局唯一标识符
文件编号
记录包装
记录线性属性
间隔
记录对数属性
间隔
记录线性平均属性
间隔
平均间隔
样本大小
记录步骤属性
间隔
计数
时长
记录事件属性
采样间隔
默认间隔
高阈值
低阈值
更改阈值
自上次记录阈值以来的变化
低流量测试属性
测试类型
起始时间
时间偏差
项目名称
操作员姓名
流通池体积
到水的初始深度
最终水位下降
总系统体积
总泵送量
井属性
套管类型
直径
长度
总深度
到屏幕的深度
屏幕长度
泵属性
模型
流速
体积
从外壳顶部送进
最终抽水率
管道属性
管道类型
直径
长度
XML 属性:
- isi-group:
定义 isi-group-members 使用的标识符,以有逻辑地组合在一起。
示例:isi-group="LocationProperties"
- isi-group-member:
将项目标识为组成员。
示例:isi-group-member="地点属性"
- isi-property:
将项目标识为"属性",格式为<Key> <Value>
<tr isi-property="Name"><td>Name = My Location</td></tr>
- isi-label:
将元素标识为本地化标签,以与值侧隔离
示例:<tr><td><span isi-label="">Name</span> = My Location</td></tr>
- isi-value:
指示解析器当前元素包含一个值 示例:
<tr><td>Name = <span isi-value="">My Location</span></td></tr>
- isi-text-node:
指示解析器该值不作为当前元素的属性存在 示例:
<tr><td isi-text-node="">Name = My Location</td></tr>
- isi-datetime:
提供 ISO 标准日期时间格式的字符串 示例:
<tr><td isi-datetime="2017-10-08T13:05:30-06:00">Start Time = 10/08/2017 1:05 PM</td> </tr>
- isi-timespan-milliseconds:
提供整数毫秒持续时间 示例:
<tr><td isi-timespan-milliseconds="3600000">Duration = 01:00:00</td></tr>
- isi-enabled: 以字符串形式提供布尔值 示例:
<tr><td isi-enabled="True">Log Wrapping Enabled = True</td></tr>
- isi-device-type: 提供一个表示设备型号(系统规范设备类型)的整数值 示例:
<tr><td isi-device-type="7">Model = Aqua TROLL 600</td></tr>
- isi-log-type: 提供一个表示类型的整数值
- isi-data-column-header: 表示当前元素是数据列标题 示例:
<tr><td isi-data-column-header="">Temperature (F)</td></tr>
- isi-device-serial-number: 提供设备序列号 示例:
<tr><td isi-device-serial-number="1234">Temperature (F)</td></tr>
- isi-sensor-serial-number: 提供传感器序列号 示例:
<tr><td isi-sensor-serial-number="4567">Temperature (F)</td></tr>
- isi-device-sensor-type: 提供传感器类型(系统规格传感器类型) 示例:
<tr><td isi-sensor-type="1">Temperature (F)</td></tr>
- isi-external-parameter: 表示传感器来自外部来源(不是仪器的一部分) 示例:
<tr><td isi-external-parameter="">Temperature (F)</td></tr>
- isi-parameter-type: 提供传感器参数类型(系统规格参数类型) 示例:
<tr><td isi-parameter-type="1">Temperature (F)</td></tr>
- isi-unit-type: 提供传感器单元类型(系统规格单元类型) 示例:
<tr><td isi-unit-type="2">Temperature (F)</td></tr>
- isi-data-table: 表示时间序列数据表的开始 示例:
<tr isi-data-table=""><td>Temperature (F)</td></tr>
- isi-data-row: 表示时序数据表的数据行 示例:
<tr isi-data-row=""><td>98.6</td><td>32.0</td><td>100.0</td></tr>
- isi-timestamp: 提供整数形式的系统规范时间(内部定义) 示例:
<tr isi-timestamp="238900"><td>07/16/1969 20:18:00</td><td>100.0</td></tr>
- isi-data-quality: 表示时序数据表的数据具有非正常质量值(系统规数据质量类型) 示例:
<tr><td>98.6</td><td>32.0</td><td>100.0</td><td isi-data-quality="3">0</td></tr>
- isi-marked: 表示时间序列数据表的数据被标记(整行) 示例:
<tr isi-marked=""><td>98.6</td><td>32.0</td><td>100.0</td></tr>
- isi-log-note: 表示当前元素是记录注释的一部分 示例:
<tr><td isi-log-note="">10/08/2012 15:30:00 Sensor Changed</td></tr>
- isi-log-note-type: 以整数形式提供记录注释类型(系统规格日志注释类型) 示例:
<tr><td isi-log-note-type="12">10/08/2012 15:30:00 Sensor Changed</td></tr>
- isi-lowflow-sample: 表示当前元素是低流量样本的一部分 示例:
<tr><td isi-lowflow-sample=""><span isi-label="">Sample #931</span>: <span isi-value="">Pre test sample</span></td></tr>
- isi-lowflow-note:
<tr><td isi-lowflow-note=""><span>Weather Conditions</span>: <span>38.5 F, 78% humidity</span></td></tr>
解析文件注意事项
- 要解析的数据从以下标签开始:
<table id="isi-report">
- 数据按表格行
<tr>
和该行中的<td>
元素组织: - 请勿基于类别属性进行解析。 类别属性仅用于 Excel 内部的格式化,应视为可选
- 根据上面列出的 XML 属性进行解析(例如:isi-group)。
解析器示例 (Python 2x)
从 HTMLParser 导入 HTMLParser
# 制作一个自定义版本的 HTML 解析器,通过覆盖来处理数据元素
class MyHTMLParser(HTMLParser):
def FeedLine(self, line, reset):
if reset:
self.startStack = [];
self.endStack = []
self.elements = []
self.feed(line)
def handle_starttag(self, tag, attrs):
self.startStack.append(tag)
self.elements.append({})
if len(attrs) > 0:
self.elements[-1]["attrs"] = attrs
def handle_endtag(self, tag):
self.endStack.append(tag)
def handle_data(self, data):
if data.strip() == "" or data.strip().rstrip() == "=":
return
if len(self.elements) < 1:
return
self.elements[-1]["data"] = data
# 从属性列表中获取所提供类型的属性
def GetAttr(attrs, ofType):
for attr in attrs:
if attr[0] == ofType:
return attr
return None
# 判断属性列表是否包含提供的类型
def ContainsAttr(attrs, ofType):
return GetAttr(attrs, ofType) is not None
# 扫描元素列表中的所有元素,查找所提供类型的属性
def GetAttrFromElements(elements, ofType):
for element in elements:
if 'attrs' not in element:
continue
for attr in element['attrs']:
if attr[0] == ofType:
return attr
return None
def GetClass(elements):
attr = GetAttrFromElements(elements, 'class')
if attr is None:
return None
else:
return attr[1]
parser = MyHTMLParser()
# 数据结构以保存文件数据
metadataGroups = {}
dataTables = []
# 打开 in-situ 数据文件
fptr = open('YOUR FILENAME HERE', 'r')
# 跳过显示 html 直接到我们感兴趣的数据
for line in fptr:
parser.FeedLine(line, True)
if 'body' in parser.startStack:
break
# 逐行读取文件以节省内存
resetLine = True
for line in fptr:
parser.FeedLine(line, resetLine)
resetLine = True
# 只对表格行感兴趣,如果不是 tr 则转到下一行
if "tr" not in parser.startStack:
continue
# 确保我们加载了整个表格行,而不仅仅是一行
if "tr" not in parser.endStack:
resetLine = False
continue
# 跳过空行
if len(parser.elements) < 1 or 'attrs' not in parser.elements[0]:
continue
startIndex = parser.startStack.index('tr')
rootAttr = parser.elements[startIndex]['attrs']
for element in parser.elements[startIndex:]:
# 如果元素没有属性我们可以忽略它
if 'attrs' not in element:
continue
if ContainsAttr(element['attrs'], 'isi-group'):
attr = GetAttr(element['attrs'], 'isi-group')
metadataGroups[attr[1]] = {}
metadataGroups[attr[1]]["Name"] = attr[1]
elif ContainsAttr(element['attrs'], 'isi-group-member'):
attr = GetAttr(element['attrs'], 'isi-group-member')
metaData = parser.elements[1]['attrs']
groupName = GetAttr(metaData, 'isi-group-member')[1]
isiProperty = GetAttr(element['attrs'], 'isi-property')
if isiProperty is not None:
label = parser.elements[2]['data']
value = parser.elements[3]['data']
metadataGroups[groupName][isiProperty[1]] = {'Label': label, 'Value': value}
logNotes = GetAttr(element['attrs'], 'isi-log-note')
if logNotes is not None:
if "Notes" not in parser.elements[1]['attrs']:
metadataGroups[groupName]["Notes"] = []
for attr in parser.elements[1]['attrs']:
metadataGroups[groupName]["Notes"].append({attr[0]:attr[1]})
elif ContainsAttr(element['attrs'], 'isi-data-table'):
dataTables.append({'Headers': [], 'Values': []})
elif ContainsAttr(element['attrs'], 'isi-data-column-header'):
hold = {'Name': element['data']}
for attr in element:
hold[attr[0]] = attr[1]
dataTables[-1]['Headers'].append(hold)
elif ContainsAttr(element['attrs'], 'isi-data-row'):
hold = []
# 此行中的所有元素都是数据,因此将它们全部处理然后中断
for element in parser.elements:
if 'attrs' in element and ContainsAttr(element['attrs'], 'isi-data-row'): # no data in the row setup
continue
elif 'data' in element:
hold.append(element['data'])
else:
hold.append(' ')
dataTables[-1]['Values'].append(hold)
# 正为文件打印出元数据。
for key in metadataGroups.iterkeys():
print (key)
print ("\t", metadataGroups[key])
print ("\n")
# 打印数据
for table in dataTables:
# 正在打印所有数据的标题行 - 注意:这里没有打印传感器类型等元数据
for header in table['Headers']:
print (header['Name'] + "\t",)
print ("")
# 正在打印数据行 - 与标题相同的顺序,使您可以正确将它们串联
for row in table['Values']:
for datum in row:
print ("|" + datum + "|",)
print ("")
解析器示例 (Python 3x)
从 html.parser 导入 HTMLParser
# 制作一个自定义版本的 HTML 解析器,通过覆盖来处理数据元素
class MyHTMLParser(HTMLParser):
def FeedLine(self, line, reset):
if reset:
self.startStack = []
self.endStack = []
self.elements = []
self.feed(line)
def handle_starttag(self, tag, attrs):
self.startStack.append(tag)
self.elements.append({})
if len(attrs) > 0:
self.elements[-1]["attrs"] = attrs
def handle_endtag(self, tag):
self.endStack.append(tag)
def handle_data(self, data):
if data.strip() == "" or data.strip().rstrip() == "=":
return
if len(self.elements) < 1:
return
self.elements[-1]["data"] = data
# 从属性列表中获取所提供类型的属性
def GetAttr(attrs, ofType):
for attr in attrs:
if attr[0] == ofType:
return attr
return None
# 判断属性列表是否包含提供的类型
def ContainsAttr(attrs, ofType):
return GetAttr(attrs, ofType) is not None
# 扫描元素列表中的所有元素,查找所提供类型的属性
def GetAttrFromElements(elements, ofType):
for element in elements:
if 'attrs' not in element:
continue
for attr in element['attrs']:
if attr[0] == ofType:
return attr
return None
def GetClass(elements):
attr = GetAttrFromElements(elements, 'class')
if attr is None:
return None
else:
return attr[1]
parser = MyHTMLParser()
# 数据结构以保存文件数据
metadataGroups = {}
dataTables = []
# 打开 in-situ 数据文件
fptr = open('YOUR FILENAME HERE', 'r')
# 跳过显示 html 直接到我们感兴趣的数据
for line in fptr:
parser.FeedLine(line, True)
if 'body' in parser.startStack:
break
# 逐行读取文件以节省内存
resetLine = True
for line in fptr:
parser.FeedLine(line, resetLine)
resetLine = True
# 只对表格行感兴趣,如果不是 tr 则转到下一行
if "tr" not in parser.startStack:
continue
# 确保我们加载了整个表格行,而不仅仅是一行
if "tr" not in parser.endStack:
resetLine = False
continue
# 跳过空行
if len(parser.elements) < 1 or 'attrs' not in parser.elements[0]:
continue
startIndex = parser.startStack.index('tr')
rootAttr = parser.elements[startIndex]['attrs']
for element in parser.elements[startIndex:]:
# 如果元素没有属性我们可以忽略它
if 'attrs' not in element:
continue
if ContainsAttr(element['attrs'], 'isi-group'):
attr = GetAttr(element['attrs'], 'isi-group')
metadataGroups[attr[1]] = {}
metadataGroups[attr[1]]["Name"] = attr[1]
elif ContainsAttr(element['attrs'], 'isi-group-member'):
attr = GetAttr(element['attrs'], 'isi-group-member')
metaData = parser.elements[1]['attrs']
groupName = GetAttr(metaData, 'isi-group-member')[1]
isiProperty = GetAttr(element['attrs'], 'isi-property')
if isiProperty is not None:
label = parser.elements[2]['data']
value = parser.elements[3]['data']
metadataGroups[groupName][isiProperty[1]] = {'Label': label, 'Value': value}
logNotes = GetAttr(element['attrs'], 'isi-log-note')
if logNotes is not None:
if "Notes" not in parser.elements[1]['attrs']:
metadataGroups[groupName]["Notes"] = []
for attr in parser.elements[1]['attrs']:
metadataGroups[groupName]["Notes"].append({attr[0]:attr[1]})
elif ContainsAttr(element['attrs'], 'isi-data-table'):
dataTables.append({'Headers': [], 'Values': []})
elif ContainsAttr(element['attrs'], 'isi-data-column-header'):
hold = {'Name': element['data']}
for attr in element:
hold[attr[0]] = attr[1]
dataTables[-1]['Headers'].append(hold)
elif ContainsAttr(element['attrs'], 'isi-data-row'):
hold = []
# 此行中的所有元素都是数据,因此将它们全部处理然后中断
for element in parser.elements:
if 'attrs' in element and ContainsAttr(element['attrs'], 'isi-data-row'): # no data in the row setup
continue
elif 'data' in element:
hold.append(element['data'])
else:
hold.append(' ')
dataTables[-1]['Values'].append(hold)
# 正为文件打印出元数据。
for key in metadataGroups.keys():
print (key)
print ("\t", metadataGroups[key])
print ("\n")
# 打印数据
for table in dataTables:
# 正在打印所有数据的标题行 - 注意:这里没有打印传感器类型等元数据
for header in table['Headers']:
print (header['Name'] + "\t",)
print ("")
# 正在打印数据行 - 与标题相同的顺序,使您可以正确将它们串联
for row in table['Values']:
for datum in row:
print ("|" + datum + "|",)
print ("")
h2 id="sampleFiles">VuSitu HTML 文件示例