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

发布于 2024-10-15 16:58:15 字数 511 浏览 5 评论 0原文

我正在解决一个问题,从我们的程序导出的 XML 没有转义引号(将 " 转换为 ",),导致接收端出现问题它可以很好地转义 &s 和尖括号,但不能转义引号。

当我深入研究 XML 导出代码时,我发现它是一个非常简单的 IXmlDomDocument2 DOM 接口。在通过调用 .XML 方法生成 XML 字符串输出的步骤中,我碰上了无法追踪的专有性之墙,因为所有工作都在 C:\Windows\System32\msxml3.dll

显然,Microsoft 的 IXmlDomDocument2 实现知道如何转义某些符号,但不知道如何转义其他符号,而更糟糕的是,这是显而易见但丑陋的解决方案。 ,(通过递归遍历整个文档并在调用 .XML 之前将值中的所有引号替换为 '"' 来运行预处理步骤,)将不起作用,因为 .XML 方法将看到其中的 & 并转义它们!有什么办法可以解决这个问题吗?

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.

When I dug around in the XML export code, I found that it was a pretty straightforward IXmlDomDocument2 DOM interface. 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.

So apparently Microsoft's IXmlDomDocument2 implementation knows how to escape some symbols but not others. 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

紙鸢 2024-10-22 16:58:15

这可以被视为另一端使用的 XML 解析器中的错误。 XML 规范详细说明了可以转义的实体。但它们只需要在属性内部转义,其工作原理如下所示:

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.

但现实是您可能无法控制等式的另一边。
因此,您可以通过执行以下操作获得所需的行为:

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.

This could be considered a bug in the XML Parser used on the other end. The XML Specification details the entities that can be escaped. 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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文