delphi xml childnodes.findnode不适用于CDATA
我有一个来自 Garmin 设备的 XML 文件,其中未找到 name
标签,因为其中包含 CDATA
。
这不是标准的,大多数 XML 文件没有这个 CDATA
,然后 FindNode()
可以正常工作。
如果我在下面的示例中查找 number
,它会正常工作。
我该如何解决这个问题?
<trk>
<name><![CDATA[Drawn track]]></name>
<src><![CDATA[MapToaster iOS]]></src>
<number>433385247</number>
LNode := TRKNode.ChildNodes.FindNode('name','');
if (LNode <> nil) and (LNode.IsTextElement) then
begin
AName := LNode.Text;
SLocalLog('(GetTracks) Name= ' + AName + '+TRKNode.ChildNodes.Count=' + IntToStr(TRKNode.ChildNodes.Count));
end;
if AName = '' then
begin
LocalLog('(GetTracks) Name=empty, continue', d_warning);
continue;
end;
编辑:
XML 文件的完整开头如下所示:
<?xml version="1.0" encoding="utf-8"?>
<gpx version="1.1" creator="MapToaster for iOS V3.5" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<metadata>
<time>2022-03-28T07:24:24.207Z</time>
</metadata>
<trk>
<name><![CDATA[Drawn track]]></name>
<src><![CDATA[MapToaster iOS]]></src>
...
编辑:
以下代码有效:
function FindNodeEx(ID: string; Nodes: IXMLNodelist):IXMLNode;
var
i: integer;
begin
result := nil;
for i := 0 to Nodes.Count-1 do
begin
SLocalLog(i.ToString+': '+Nodes[i].NodeName);
if Nodes[i].NodeName = 'name' then
begin
SLocalLog('FindNodeEx: ID found: ='+Nodes[i].Text);
result := Nodes[i];
if result.NodeType = TNodeType.ntCData then SLocalLog('FindNodeEx: CDATA found'); // This does not happen.
SLocalLog('FindNodeEx: NodeType='+IntToStr(integer(result.NodeType))); // Shows as 'Element'
exit;
end;
end;
SLocalLog('FindNodeEx: ID not found: '+ID,d_warning);
end;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的XML文档正在使用命名空间,但是您对
findNode()
的使用正在告诉它忽略命名空间。因此,在调用findNode()
时,应指定正确的名称空间。另外,即使
findNode()
成功地找到了节点,ixmlnode.istextlement
属性不支持cdata
content,只有普通文本内容。这甚至是 comporded行为。但是,属性将愉快地返回
cdata
content(您可能会或不得不手动解码,我不确定) - 至少在现代版本中( wither版本不支持此)。尝试更多这样的东西:
Your XML document is using namespaces, but your use of
FindNode()
is telling it to ignore namespaces. So, you should specify the correct namespace when callingFindNode()
.Also, even if
FindNode()
were successful in finding the node, theIXMLNode.IsTextElement
property does not supportCDATA
content, only plain text content. This is even documented behavior.However, the
IXMLNode.Text
property will happily returnCDATA
content (which you may or may not have to decode manually, I'm not sure) - at least in modern versions (older versions didn't support this).Try something more like this: