delphi 无法通过TXMLDocument枚举XML树

6xfqseft  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(155)

我尝试在 Delphi 中使用TXMLDocument来枚举XML文件。但是每当我退出ProcessFile过程时,都会出现“Access violation”异常。
我将XMLFile声明为接口对象IXMLDocument,而不是TXMLDocument,并且不手动调用free。
下面是代码:

  1. // Invoke ProcessFile in the main app
  2. ProcessFile('C:\Myfile.xlf', True);
  3. // Process the node recursively
  4. procedure ProcessNode1(Node: IXMLNode);
  5. var
  6. Index: Integer;
  7. begin
  8. if (Node.NodeName = 'trans-unit') then
  9. begin
  10. // Process 'trans-unit'
  11. end
  12. else
  13. for Index := 0 to Node.ChildNodes.Count - 1 do
  14. ProcessNode1(Node.ChildNodes[Index]);
  15. end;
  16. procedure ProcessFile(const SrcFileName: string; const FixMode: Boolean);
  17. var
  18. XmlFile: IXMLDocument;
  19. MainNode, FileNode: IXMLNode;
  20. OriginalFileName, SrcLang, DstLang: string;
  21. begin
  22. // Initialize the COM, otherwise we cannot use MSXML
  23. CoInitialize(nil);
  24. // Open the XML document
  25. XmlFile := TXMLDocument.Create(nil);
  26. try
  27. XmlFile.LoadFromFile(SrcFileName);
  28. // XmlFile.Active := True;
  29. MainNode := XmlFile.DocumentElement;
  30. FileNode := MainNode.ChildNodes['file'];
  31. OriginalFileName := FileNode.GetAttribute('original');
  32. SrcLang := FileNode.GetAttribute('source-language');
  33. DstLang := FileNode.GetAttribute('target-language');
  34. // Output the information
  35. // If removing the following statement, then everything will be OK.
  36. Writeln(Format('Call TranslateFile. OriginFile: %s. SrcFile: %s. SrcLang: %s. DstLang: %s. FixMode: %s.',
  37. [OriginalFileName, ExtractFileName(SrcFileName), SrcLang, DstLang, BoolToStr(FixMode, True)]));
  38. // Enumerate the DOM tree
  39. ProcessNode1(FileNode);
  40. finally
  41. CoUninitialize;
  42. end;
  43. end;

Blow是XML文档

  1. <?xml version="1.0" encoding="utf-16"?>
  2. <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">
  3. <file original="a.rc" source-language="en-US" target-language="bg-BG" datatype="plaintext">
  4. <body>
  5. <group id="String" datatype="winres">
  6. <group id="IDS_TEST">
  7. <trans-unit id="String.IDS_TEST1">
  8. <source>a</source>
  9. <target state="translated" state-qualifier="fuzzy-match">b</target>
  10. <soluling:datatype>string</soluling:datatype>
  11. <soluling:rowstatus>rsInUse</soluling:rowstatus>
  12. </trans-unit>
  13. </group>
  14. </group>
  15. </body>
  16. </file>
  17. </xliff>
xzlaal3s

xzlaal3s1#

XmlFileMainNodeFileNode对象仍然处于活动状态时,您正在调用CoUninitialize(),因此当它们在ProcessFile()退出时超出作用域时,RTL无法正确释放它们,因此出现了访问冲突。
在卸载COM库之前,您需要清除这些引用,例如:

  1. procedure ProcessFile(const SrcFileName: string; const FixMode: Boolean);
  2. var
  3. XmlFile: IXMLDocument;
  4. MainNode, FileNode: IXMLNode;
  5. ...
  6. begin
  7. // Initialize the COM, otherwise we cannot use MSXML
  8. CoInitialize(nil);
  9. try
  10. // Open the XML document
  11. XmlFile := LoadXMLDocument(SrcFileName);
  12. try
  13. MainNode := XmlFile.DocumentElement;
  14. FileNode := MainNode.ChildNodes['file'];
  15. ...
  16. finally
  17. // ADD THIS!
  18. FileNode := nil;
  19. MainNode := nil;
  20. XmlFile := nil;
  21. end;
  22. finally
  23. CoUninitialize;
  24. end;
  25. end;

或者,将COM库的加载/卸载与树处理代码分开,例如:

  1. procedure DoProcessFile(const SrcFileName: string; const FixMode: Boolean);
  2. var
  3. XmlFile: IXMLDocument;
  4. MainNode, FileNode: IXMLNode;
  5. ...
  6. begin
  7. // Open the XML document
  8. XmlFile := LoadXMLDocument(SrcFileName);
  9. MainNode := XmlFile.DocumentElement;
  10. FileNode := MainNode.ChildNodes['file'];
  11. ...
  12. end;
  13. procedure ProcessFile(const SrcFileName: string; const FixMode: Boolean);
  14. begin
  15. // Initialize the COM, otherwise we cannot use MSXML
  16. CoInitialize(nil);
  17. try
  18. DoProcessFile(SrcFileName, FixMode);
  19. finally
  20. CoUninitialize;
  21. end;
  22. end;
展开查看全部

相关问题