我有一個來自 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;
uj5u.com熱心網友回復:
您的 XML 檔案正在使用名稱空間,但您的使用FindNode()是告訴它忽略名稱空間。因此,您應該在呼叫時指定正確的命名空間FindNode()。
此外,即使FindNode()成功找到節點,該IXMLNode.IsTextElement屬性也不支持CDATA內容,僅支持純文本內容。這甚至是記錄在案的行為。
但是,該IXMLNode.Text屬性將愉快地回傳CDATA內容(您可能需要或可能不需要手動解碼,我不確定) - 至少在現代版本中(舊版本不支持此功能)。
嘗試更多類似的東西:
function IsTextOrCDataElement(const ANode: IXMLNode): Boolean;
begin
Result := (ANode.NodeType = ntElement) and
(ANode.DOMNode.childNodes.length = 1) and
(ANode.DOMNode.childNodes[0].nodeType in [TEXT_NODE, CDATA_SECTION_NODE]);
end;
function RemoveCData(const AData: string): string;
begin
if StartsText('<![CDATA[', AData) and EndsText(']]>', AData) then
Result := Copy(AData, 10, Length(AData)-12)
else
Result := AData;
end;
...
LNode := TRKNode.ChildNodes.FindNode('name', 'http://www.topografix.com/GPX/1/1');
if (LNode <> nil) and IsTextOrCDataElement(LNode) then
begin
AName := RemoveCData(LNode.Text);
// or just:
// AName := LNode.Text;
// or:
// AName := LNode.NodeValue;
...
end;
...
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/460947.html
