简体   繁体   English

如何使IXmlDomDocument2.XML正确转义引号?

[英]How to get IXmlDomDocument2.XML to escape quotes properly?

I'm working on a problem where XML exported from our program doesn't escape quotes, (turning " into " ,) leading to problems on the receiving end. It escapes &s and angle brackets just fine, but not quotes. 我正在解决一个问题,即从我们的程序中导出的XML不会转义引号(将"变成" ,)导致接收端出现问题,它会正确地转义&s和尖括号,但不会转引号。

When I dug around in the XML export code, I found that it was a pretty straightforward IXmlDomDocument2 DOM interface. 在研究XML导出代码时,我发现它是一个非常简单的IXmlDomDocument2 DOM接口。 But when I got to the step where it produces the XML string output by calling the .XML method, I ran smack into a wall of proprietariness that I can't trace into, since all the work is taking place inside of C:\\Windows\\System32\\msxml3.dll . 但是当我到达通过调用.XML方法生成XML字符串输出的步骤时,我碰到了我无法追踪的专有性墙,因为所有工作都在C:\\Windows\\System32\\msxml3.dll内部进行C:\\Windows\\System32\\msxml3.dll

So apparently Microsoft's IXmlDomDocument2 implementation knows how to escape some symbols but not others. 因此,显然,Microsoft的IXmlDomDocument2实现知道如何转义某些符号,而不能转义其他符号。 And just to make it worse, the obvious but ugly solution, (running a preprocessing step by recursively traversing the entire document and replacing all quotes in values with '"' before I call .XML ,) won't work because the .XML method will see those &s in there and escape them! Is there any way to fix this? 而且,更糟糕的是,显而易见的,丑陋的解决方案(通过递归遍历整个文档并在我调用.XML之前用'“'替换值中的所有引号来运行预处理步骤)将不起作用,因为.XML方法会看到那些&s在那里并逃脱它们!有什么办法可以解决这个问题?

This could be considered a bug in the XML Parser used on the other end. 可以将其视为另一端使用的XML解析器中的错误。 The XML Specification details the entities that can be escaped. XML规范详细说明了可以转义的实体。 But they only need to be escaped inside the attributes, which works as shown here: 但是它们只需要在属性内进行转义,如下所示:

program Project2;

{$APPTYPE CONSOLE}

uses
  ActiveX,
  MSXML2_TLB,
  SysUtils;
var
  Dom : IXMLDOMDocument2;
  Root :  IXMLDOMNode;
  Attr : IXMLDOMNode;
begin
  CoInitialize(nil);
  try
    DOM := CoDOMDocument40.Create;
    Root := Dom.createElement('root');
    Attr := Dom.createAttribute('attr');
    Attr.text := '"';
    root.attributes.setNamedItem(Attr);
    root.text := '"Hello World"';
    DOM.appendChild(Root);
    writeln(Root.xml);
    readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

But the reality is that you may not have control over the other side of the equation. 但是现实是您可能无法控制方程式的另一端。 So you can get the desired behavior doing the following: 因此,您可以执行以下操作来获得所需的行为:

program Project2;

{$APPTYPE CONSOLE}

uses
  ActiveX,
  MSXML2_TLB,
  SysUtils;
function QuoteEscape(const v : String) : String;
begin
  result := StringReplace(V,'"','"',[rfReplaceAll]);
end;


var
  Dom : IXMLDOMDocument2;
  Root :  IXMLDOMNode;
  Attr : IXMLDOMNode;
begin
  CoInitialize(nil);
  try
    DOM := CoDOMDocument40.Create;
    Root := Dom.createElement('root');
    Attr := Dom.createAttribute('attr');
    Attr.text := '"';
    root.attributes.setNamedItem(Attr);
    root.text :=  QuoteEscape('"Hello World"');
    DOM.appendChild(Root);
    writeln(StringReplace(Root.xml,'"','"',[rfReplaceAll]));
    readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM