如何在 MATLAB 中使用 XML 文件按数字查找对应标签?
先用 xmlread 读取 XML,将数字和标签的对应关系存入 containers.Map,再遍历数字数组,逐个取出标签。这样只需解析一次 XML,后续查询都通过映射表完成。
具体写法取决于 XML 的结构。这里没有实际文件,示例假设数字保存在 id 属性中,标签文本保存在 label 属性中。
1. 准备 XML 文件
将以下内容保存为 lookup.xml,放在 MATLAB 当前文件夹中:
<?xml version="1.0" encoding="UTF-8"?>
<lookup>
<item id="10" label="Apple"/>
<item id="20" label="Banana"/>
<item id="30" label="Orange"/>
</lookup>
其中:
lookup是根元素,包含所有记录。- 每个
item元素是一条记录。 id="10"表示查找用的数字,label="Apple"是对应的文本。
XML 属性值都是文本,读取 id 后需要将其转换为 MATLAB 数值。
2. 读取 XML 并建立查找表
以下代码使用 xmlread 返回的 Java DOM 接口,MATLAB 环境需要支持该接口并启用 JVM。
% 读取 XML 文件
doc = xmlread('lookup.xml');
% 获取所有名为 item 的元素
items = doc.getElementsByTagName('item');
% 创建查找表:键为 double,值为字符向量
lookup = containers.Map('KeyType', 'double', 'ValueType', 'char');
for i = 0:(items.getLength() - 1)
node = items.item(i);
% 检查每条记录是否包含所需属性
if ~node.hasAttribute('id') || ~node.hasAttribute('label')
error('第 %d 条记录缺少 id 或 label 属性。', i + 1);
end
% 将 XML 属性转换为 MATLAB 数据
idText = char(node.getAttribute('id'));
id = str2double(idText);
label = char(node.getAttribute('label'));
if ~isfinite(id)
error('第 %d 条记录的 id 不是有效的有限数值。', i + 1);
end
% 每个数字只能对应一个标签
if isKey(lookup, id)
error('XML 中存在重复的 id:%g。', id);
end
lookup(id) = label;
end
doc 是 XML 文档的 DOM 对象,可以理解为一棵由元素和属性组成的树。getElementsByTagName('item') 会找到文档中所有名为 item 的元素,也包括嵌套在其他元素中的记录。
DOM 的 item(i) 从 0 开始编号,MATLAB 数组通常从 1 开始编号,因此这里的循环范围是 0 到 getLength()-1。
查找表建好后,可以直接查询单个数字:
lookup(20)
示例中的查询结果是 'Banana'。
3. 根据数字数组获取标签
假设要查询的数字数组为:
numbers = [20 10 30 20];
按数组原有顺序逐个查找:
labels = cell(size(numbers));
for k = 1:numel(numbers)
id = numbers(k);
if ~isKey(lookup, id)
error('查找表中没有数字 %g。', id);
end
labels{k} = lookup(id);
end
disp(labels);
得到的 labels 为:
{'Banana', 'Apple', 'Orange', 'Banana'}
不同标签的长度可以不同,因此这里用元胞数组 cell 保存文本。labels{k} 用于取出第 k 个元胞中的标签,例如:
labels{1}
结果是 'Banana'。
cell(size(numbers)) 会保留输入数组的形状。如果 numbers 是列向量,结果也是列形式的元胞数组。
4. XML 结构不同时,如何修改代码?
如果数字和标签保存在子元素中,例如:
<lookup>
<item>
<id>10</id>
<label>Apple</label>
</item>
</lookup>
就需要读取元素的文本内容。假设每个 item 中恰好有一个 id 和一个 label,将前面循环中检查和读取属性的部分替换为:
idNodes = node.getElementsByTagName('id');
labelNodes = node.getElementsByTagName('label');
if idNodes.getLength() ~= 1 || labelNodes.getLength() ~= 1
error('每条 item 记录必须包含一个 id 和一个 label 元素。');
end
idNode = idNodes.item(0);
labelNode = labelNodes.item(0);
id = str2double(char(idNode.getTextContent()));
label = strtrim(char(labelNode.getTextContent()));
后面的数值检查、重复检查和 lookup(id) = label 保持原样。strtrim 会去掉标签文本两端的空白;如果这些空白有实际含义,应去掉这次 strtrim 调用。
标签文本和 XML 元素名也要区分。在 <item id="10" label="Apple"/> 中,元素名是 item,标签文本是 Apple。如果需要获取元素名,可以使用:
elementName = char(node.getNodeName());
5. 使用时需要注意什么?
- 文件不在当前文件夹时,向
xmlread传入正确的相对路径或完整路径。可以用pwd查看当前文件夹。 - XML 名称区分大小写,
item和Item是不同的元素名。对于带命名空间的 XML,需要相应调整节点选择方式。 - 示例要求每个数字只对应一个标签,遇到重复
id会报错。如果一个数字可以对应多个标签,需要改用能保存多个值的数据结构。 - 输入数字不在查找表中时,代码会停止并报错。如果希望继续处理,可以将对应的
labels{k}设为'',再用continue跳过本次查询。 - 数值键按精确值匹配。浮点计算结果可能与 XML 中的数值有微小差异,需要按业务规则统一精度。
- 如果编号中的前导零有意义,例如
"0010"与"10"必须区分,应使用文本键。超过double精确整数表示范围的长编号也应保留为文本。
备注:内容仅供参考。
