针对&的解决方法和Delphi XE4中的CRLF问题以及TXMLTransformProvider组件

时间:2014-07-26 02:45:33

标签: xml delphi delphi-7 delphi-xe4

我知道这将是一个重复的问题,但仍然要求再次解决这个问题没有解决办法。让我先解释一下问题陈述,然后我也会提到我的尝试。

XML:

<Order><XMLversion>2</XMLversion><Info>*-first line
*-second line</Info></Order>

CRLF在“* -first line”语句后面。

我使用Delphi XE4 RAD Studio 工具 - &gt;创建了与此XML对应的 XTR文件。 XML Mapper 实用程序。关注XTR文件后我得到了:

<XmlTransformation Version="1.0"><Transform Direction="ToCds"><SelectEach dest="DATAPACKET\ROWDATA\ROW" from="\Order"><Select dest="@XMLversion" from="\XMLversion"/><Select dest="@Info" from="\Info"/></SelectEach></Transform><XmlSchema RootName="Order"><![CDATA[<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <element xmlns="http://www.w3.org/2001/XMLSchema" name="Order" type="OrderType"/>
  <complexType xmlns="http://www.w3.org/2001/XMLSchema" name="OrderType">
    <sequence>
      <element name="XMLversion" type="XMLversionType"/>
      <element name="Info" type="InfoType"/>
    </sequence>
  </complexType>
  <element xmlns="http://www.w3.org/2001/XMLSchema" name="XMLversion" type="XMLversionType"/>
  <simpleType xmlns="http://www.w3.org/2001/XMLSchema" name="XMLversionType">
    <restriction base="xs:string"/>
  </simpleType>
  <element xmlns="http://www.w3.org/2001/XMLSchema" name="Info" type="InfoType"/>
  <simpleType xmlns="http://www.w3.org/2001/XMLSchema" name="InfoType">
    <restriction base="xs:string"/>
  </simpleType>
</xs:schema>]]></XmlSchema><CdsSkeleton/><XslTransform/><Skeleton><![CDATA[<?xml version="1.0"?><DATAPACKET Version="2.0"><METADATA><FIELDS><FIELD attrname="XMLversion" fieldtype="string" WIDTH="1"/><FIELD attrname="Info" fieldtype="bin.hex" SUBTYPE="Text"/></FIELDS><PARAMS/></METADATA><ROWDATA/><METADATA><FIELDS><FIELD attrname="XMLversion" fieldtype="string" WIDTH="1"/><FIELD attrname="Info" fieldtype="bin.hex" SUBTYPE="Text"/></FIELDS><PARAMS/></METADATA><ROWDATA/></DATAPACKET>
]]></Skeleton></XmlTransformation>

问题陈述:

在我的dfm文件中,我将 TXMLTransformProvider Clientdataset 。在TXMLTransformProvider中,我提供了XML和XTR文件的路径。 TClientdataset的ProviderName设置为TXMLTransformProvider。

以下是我从XML中读取“info”节点的代码。

procedure TfrmAmpersand.Issue;
var
  InfoNode : Variant;
begin
  try
    InfoNode := ClientDataset1.FieldByName('Info').AsVariant;
    ShowMessage(InfoNode);
  except on e:exception do
    begin
      ShowMessage(e.Message);
    end;
  end;
end;

XML中有两个字段:XMLVersion和Info。在Clientdataset中,XMLVersion是TStringField,而Info是TMemoField。

ShowMessage(InfoNode),显示如下消息

*-first line&*-second line

对于Delphi 7,它工作正常并显示如下信息:

*-first line
*-second line

以下是我的Dropbox链接,我已针对此问题上传了我的示例项目:

https://www.dropbox.com/s/foi7o3wf7wlx9lh/AmpersandIssue.zip

请注意,我已将XML和XTR文件的硬编码路径放在TXMLTransformProvider中。因此,请将此项目保留在D:驱动器中,或者只更改TXMLTransformProvider中的路径。

以下是EDN链接,我提出了同样的问题,但没有得到回复:

https://forums.embarcadero.com/thread.jspa?messageID=667134&#667134

我尝试过的解决方法:

  1. 替换&amp;获得该节点值后,使用#13#10

    InfoNode:= StringReplace(InfoNode,'&amp;',#13#10,[rfReplaceAll]);

  2. 但这不是正确的解决方案,因为信息节点实际上可以包含&amp;在数据库中。

    1. 我尝试了他在上一个问题中提供的所有 Remy的解决方案
    2. 我将XML硬编码为:

      <Order><XMLversion>2</XMLversion><Info>*-first line&#13;&#10;*-second line</Info></Order>
      

      <Order><XMLversion>2</XMLversion><Info>*-first line&#xD;&#xA;*-second line</Info></Order>
      

      以及

      <Order><XMLversion>2</XMLversion><Info><![CDATA[*-first line
      *-second line]]></Info></Order>
      

      没有任何效果。每次我得到的结果与上面提到的相同。 &符号。

      1. Ken White的回答对我来说也不起作用,他在上一个问题中提供了我。

      2. @TLama - 您在上一个问题中建议我(抱歉,但由于某些原因我已将其删除),这是TXMLTransformProvider中的错误和我应该带着雷米的解决方案。但现在没有任何工作。那么我应该采取哪些后续步骤来解决这个直接的问题呢?你有没有用Embarcadero提出这个错误?

      3. 请建议我解决此问题的任何解决方法?

1 个答案:

答案 0 :(得分:4)

我需要在回答这个问题时说,与Remy或Ken不同,我绝对不是Unicode的专家,我甚至不确定它是否与您的问题有关。

但是,我查看了XMLTransformProvider生成的磁盘上字节,并将其与执行CDS.SaveToFile('Test.Xml',dfXML)时写入磁盘的内容进行了比较。

很明显,CDS会将嵌入在DB备忘录字段中的换行符保存为:

&#013;&#010;

XMLTransformProvider为类似换行生成的内容是:

&#xA;

因此,我的简单建议解决方法是连接到您打开XML数据文件的代码,以便以自己的格式加载带有XML的CDS:

const 
  TransformNewLine = '&#xA;';
  CDSNewLine = '&#013;&#010;';

function FixCdsXml(Input : String) : String;
begin
  Result:= StringReplace(Input, TransformNewLine, CDSNewLine, [rfReplaceAll]);
end;

procedure TfrmAmpersand.TestFix;
var
  S : String;
  SS : TStringStream;
begin
  S := XMLTransformProvider1.TransformRead.Data;
  S := FixCdsXml(S);
  SS := TStringStream.Create(S);
  try
    SS.Position := 0;
    ClientDataSet1.LoadFromStream(SS);
  finally
    SS.Free;
  end;
end;

TXMLTransformerProvider或其TXMLTransform子组件中似乎没有任何方便的事件可用作自动调用TestFix的机会。但是,如果你在CDS的AfterOpen事件中调用它似乎工作正常,前提是你在表单中添加了一个“FixingXML”布尔值以防止重新入侵并像这样编码事件:

procedure TfrmAmpersand.ClientDataSet1AfterOpen(DataSet: TDataSet);
begin
  if FixingXML then exit;
  FixingXML := True;
  try
    TestFix;
  finally
    FixingXML := False;
  end;
end;

我正在使用XE6,顺便说一句。