我正在编写一个C++程序,我需要从TIF文件中读取一段元数据。元数据是一个字符串,如下所示:
<GDALMetadata>
<Item name="BANDWIDTH"></Item>
<Item name="CENTER_FILTER_WAVELENGTH"></Item>
<Item name="DATA_SET_ID">&quot;LRO-L-LOLA-4-GDR-V1.0&quot;</Item>
<Item name="FILTER_NAME"></Item>
<Item name="INSTRUMENT_ID">&quot;LOLA&quot;</Item>
<Item name="INSTRUMENT_NAME">&quot;LUNAR ORBITER LASER ALTIMETER&quot;</Item>
<Item name="MISSION_NAME"></Item>
<Item name="NOTE"></Item>
<Item name="PRODUCER_INSTITUTION_NAME">&quot;GODDARD SPACE FLIGHT CENTER&quot;</Item>
<Item name="PRODUCT_CREATION_TIME">2017-09-15</Item>
<Item name="START_TIME">2009-07-13T17:33:17</Item>
<Item name="STOP_TIME">2016-11-29T05:48:19</Item>
<Item name="OFFSET" sample="0" role="offset">1737400</Item>
<Item name="SCALE" sample="0" role="scale">0.5</Item>
</GDALMetadata>
我需要提取scale
值(在本例中为0.5)。我的第一个尝试是使用regex,如下所示:
float scale = 1;
std::regex rgx("*<Item name=\"SCALE\"*>(.*?)</Item>*");
std::smatch match;
if (std::regex_search(metadata.begin(), metadata.end(), match, rgx)) {
scale = static_cast<float>(std::atof(match.str().c_str()));
};
这不起作用,我不知道为什么。我对正则表达式非常缺乏经验。
显然这看起来像HTML,但因为我只需要这一个特定的领域,我想它应该是简单的尝试直接提取。
4条答案
按热度按时间mtb9vblg1#
我认为使用
std::regex
是对元数据未来格式的过多假设,因为它是XML文本。XML可以被打乱,包含break和不同的顺序。我倾向于使用能够解析和处理XML的库,如libxml2或boost::property_tree
Link。
以下示例分析元数据并打印比例。
结果
Godbolt:https://godbolt.org/z/K94EW9YMf
qq24tv8q2#
你的正则表达式字符串文字应该是这样的:
"<Item name=\"SCALE\"[^>]*>(.*?)<\\/Item>"
IOW,去掉前面和后面的
*
,你不需要它们。使用[^>]*
而不仅仅是*
来忽略"SCALE"
之后的所有内容,但不包括>
。并且需要在</Item>
中转义/
(在正则表达式本身中,而不是在字符串字面量中)。也就是说,
match.str()
将返回与正则表达式匹配的整个子字符串,而不是您期望的(.*?)
组中的值。因此,std::atof()
将接收到无效字符串并失败。要只提取组值,请改用match[1].str()
。最后,考虑使用
std::stof()
而不是atof()
。试试这个:
Online Demo
zaq34kh63#
你可以找到两个分隔符
role="scale">
和</Item>
之间的子字符串,首先你可以删除role="scale">
之前的所有</Item>
示例,这样子字符串就可以正常工作,然后使用metadata.substr()
和metadata.find()
找到role="scale">
和</Item>
之间的子字符串。igsr9ssn4#
我会用老办法。读取字符串,直到找到带有单词“scale”的字符串,然后更详细地解析这个字符串:
这段代码提出了一个总体思路或解决方案;可能会有问题