I try to use TXMLDocument in Delphi to enumerate a XML file. But whenever I exit the ProcessFile procedure, there will be an "Access violation" exception.
I declare XMLFile as an interface object IXMLDocument, instead of TXMLDocument, and do not call free it manually.
Below is the code:
// Invoke ProcessFile in the main app
ProcessFile('C:\Myfile.xlf', True);
// Process the node recursively
procedure ProcessNode1(Node: IXMLNode);
var
Index: Integer;
begin
if (Node.NodeName = 'trans-unit') then
begin
// Process 'trans-unit'
end
else
for Index := 0 to Node.ChildNodes.Count - 1 do
ProcessNode1(Node.ChildNodes[Index]);
end;
procedure ProcessFile(const SrcFileName: string; const FixMode: Boolean);
var
XmlFile: IXMLDocument;
MainNode, FileNode: IXMLNode;
OriginalFileName, SrcLang, DstLang: string;
begin
// Initialize the COM, otherwise we cannot use MSXML
CoInitialize(nil);
// Open the XML document
XmlFile := TXMLDocument.Create(nil);
try
XmlFile.LoadFromFile(SrcFileName);
// XmlFile.Active := True;
MainNode := XmlFile.DocumentElement;
FileNode := MainNode.ChildNodes['file'];
OriginalFileName := FileNode.GetAttribute('original');
SrcLang := FileNode.GetAttribute('source-language');
DstLang := FileNode.GetAttribute('target-language');
// Output the information
// If removing the following statement, then everything will be OK.
Writeln(Format('Call TranslateFile. OriginFile: %s. SrcFile: %s. SrcLang: %s. DstLang: %s. FixMode: %s.',
[OriginalFileName, ExtractFileName(SrcFileName), SrcLang, DstLang, BoolToStr(FixMode, True)]));
// Enumerate the DOM tree
ProcessNode1(FileNode);
finally
CoUninitialize;
end;
end;
Blow is the XML document
<?xml version="1.0" encoding="utf-16"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd" xmlns:soluling="http://www.soluling.com">
<file original="a.rc" source-language="en-US" target-language="bg-BG" datatype="plaintext">
<body>
<group id="String" datatype="winres">
<group id="IDS_TEST">
<trans-unit id="String.IDS_TEST1">
<source>a</source>
<target state="translated" state-qualifier="fuzzy-match">b</target>
<soluling:datatype>string</soluling:datatype>
<soluling:rowstatus>rsInUse</soluling:rowstatus>
</trans-unit>
</group>
</group>
</body>
</file>
</xliff>
You are calling
CoUninitialize()while theXmlFileMainNode, andFileNodeobjects are still active, so the RTL can't release them properly when they go out of scope whenProcessFile()exits, hence the Access Violation.You need to clear those references before unloading the COM library, eg:
Alternatively, separate the loading/unloading of the COM library from your tree processing code, eg: