关于对象持久化到XML(OmniXML) ( 积分: 100 )

  • 主题发起人 主题发起人 crazycock
  • 开始时间 开始时间
C

crazycock

Unregistered / Unconfirmed
GUEST, unregistred user!
关于对象持久化到XML
看到CnPack也在使用着OmniXML(http://www.omnixml.com),他是一个可以将对象持久化到xml的控件,我用他可以实现持久化了,但是发现一个问题,SaveXML后,再LoadXML,发现对象的字体没有被恢复,它保存下来的XML代码如下:
<data PropFormat=&quot;node&quot;><TMemo><Left>24</Left><Top>40</Top><Width>297</Width><Height>233</Height><Font><Charset>1</Charset><Color>255</Color><Height>-40</Height><Name>MS Sans Serif</Name><Style>[]</Style></Font><Lines Count=&quot;1&quot;><l0>Memo1</l0></Lines><ParentFont>0</ParentFont><TabOrder>4</TabOrder></TMemo></data>
很明显,它保存了字体的属性=》<Font><Charset>1</Charset><Color>255</Color><Height>-40</Height><Name>MS Sans Serif</Name><Style>[]</Style></Font>
但是,对于字体的高度,他是保存为<Height>-40</Height>,但是,恢复的时候没有得到正常的字体属性,我手工在这段XML中添加了<Size>30</Size>,再恢复,就发现字体的大小如我所愿了。不知道这个是什么问题,OmniXML有源码的,小弟水平差,看不懂,希望前辈能够指点一下。
另外,如何在xml某节点处加入另一个xml文件的内容? 因为OmniXML可以把对象保存为一段XML代码,我想把它作为一个Node加入到其他xml文档中作为一个节点。
 
关于对象持久化到XML
看到CnPack也在使用着OmniXML(http://www.omnixml.com),他是一个可以将对象持久化到xml的控件,我用他可以实现持久化了,但是发现一个问题,SaveXML后,再LoadXML,发现对象的字体没有被恢复,它保存下来的XML代码如下:
<data PropFormat=&quot;node&quot;><TMemo><Left>24</Left><Top>40</Top><Width>297</Width><Height>233</Height><Font><Charset>1</Charset><Color>255</Color><Height>-40</Height><Name>MS Sans Serif</Name><Style>[]</Style></Font><Lines Count=&quot;1&quot;><l0>Memo1</l0></Lines><ParentFont>0</ParentFont><TabOrder>4</TabOrder></TMemo></data>
很明显,它保存了字体的属性=》<Font><Charset>1</Charset><Color>255</Color><Height>-40</Height><Name>MS Sans Serif</Name><Style>[]</Style></Font>
但是,对于字体的高度,他是保存为<Height>-40</Height>,但是,恢复的时候没有得到正常的字体属性,我手工在这段XML中添加了<Size>30</Size>,再恢复,就发现字体的大小如我所愿了。不知道这个是什么问题,OmniXML有源码的,小弟水平差,看不懂,希望前辈能够指点一下。
另外,如何在xml某节点处加入另一个xml文件的内容? 因为OmniXML可以把对象保存为一段XML代码,我想把它作为一个Node加入到其他xml文档中作为一个节点。
 
没人管没人问哦~
 
那个size问题。。应该是他没保存的原因吧,看看他源码改改喽~
至于保存到其他XML当节点。。。你要看看OmniXML有没有提供保存到一个ixmlnode的接口
 
呵呵。谢谢hs-kill的指点,最好你帮忙看看OmniXML代码,我要是能看懂自己改,就改好了,里面用到不少RTTI,我不懂。OmniXML中声明的IXMLNode和XMLIntf中声明的IXMLNode是不对等的。没法互换。只有IXMLNode.XML是对等的,都是XML内容的本质,可惜这个属性只提供了读,没法写。
 
TFont.Height才是真正的冬冬.TForn.Size并不重要.在*.dfm当中同样只保存TFont.Height,没有Size.
至于为何分析出错.我想你可以使用use Debug DCU.然后看TFont.SetHeight是否被调用,如果被调用了,那么就没有OmniXML的事情了.
因为我身边没有环境.不过既然size 可以,那么你可以检查 SetSize和SetHeight的代码,看一看他们有什么区别.这样我想可能能够找到答案
 
看来高手和低手之间还是有区别的,我请教了CnPack中的周大侠,上午发的邮件,晚上回到家一看邮箱,答案已经早趟在里面了:)
其实,这是OmniXML中的一个Bug,具体的原因周大侠解释得很清楚,可惜我没有拷贝过来到单位,不过我隐约记得应该怎么改,来到单位,然后自己竟然改出来了。哈哈哈~
在OmniXML中的OmniXMLPersistent单元中,第596、597行,原文是
else

SetOrdProp(Instance, PropInfo, PPropInfo(PropInfo)^.Default)
改成:
else
if IsStoredProp(Instance,PropInfo) then
SetOrdProp(Instance, PropInfo, PPropInfo(PropInfo)^.Default)
邮件的原文我得空再贴出来。
另外的那个“另外,如何在xml某节点处加入另一个xml文件的内容? 因为OmniXML可以把对象保存为一段XML代码,我想把它作为一个Node加入到其他xml文档中作为一个节点。
”的问题,周大侠也给出了解决办法,也已经调试通过了,而且我还做了一点改进,他给的方法是使用临时文件,然后把需要添加进来的源node用OmniXMLUtils单元中提供的CopyNode函数实现复制到目标文档中作为一个node,我做了改进,使用一个新xmldoc的loadXML方法,直接把源node.xml加载进来,然后再使用CopyNode来实现复制过来,这样避免了创建临时文件的过程,更加爽~
如果能够师从他人,日进千尺真的不是不可能啊~可惜自己还是野战军,瞎捣弄~唉~~
 
zjan521说得其实很有条理的,说不定看到代码你也能分析出来,确实设置Size也是通过设置Height实现的,那个OmniXML的Bug就是因为调用了SetHeight后,没有判断Font.Size是否被持久化就调用他来SetSize,结果我们保存下来的信息没有Size,就会调用SetSize到了默认值1,所以我们恢复出来的字体大小总是1,感觉就是没有恢复一样。唉,我还是说不清,等我贴邮件吧。
 
呵呵。。OmniXML是什么啊,第3放控件? 我没见过 呵呵~
他的那个copynode是怎么做的。。。。。。?
 
OmniXML可以把对象持久化到XML,CnPack中用到了它。
CnPack周大侠回复的邮件原文。如下:
--------------------------------
刚才我测试了一下,发现您遇到的问题是 OmniXML 的一个 Bug。
产生这个问题的原因如下:
在 Graphics 的源码中,我们可以看到 Font.Size 这个属性声明为 stored False,表示流化时不需要保存。其写方法为:
procedure TFont.SetSize(Value: Integer);
begin
Height := -MulDiv(Value, FPixelsPerInch, 72);
end;
这里可以看出修改 Size 其实是修改 Height 属性。
然而,OmniXMLPersistent 单元中,虽然在写属性时判断了 stored 状态,却没有在恢复属性时进行检查,而是对没有在 XML 中找到的属性执行了:
SetOrdProp(Instance, PropInfo, PPropInfo(PropInfo)^.Default);
导致本来已经正确设置过的 Height 属性,又在处理 Size 时被修改成了无效值(调试发现 Size 属性的 Default 为 1)。表面看来就象是 Size 没有保存似的。
我们会跟 OmniXML 的作者联系,请他发布新的官方版本来修正这个缺陷。暂时您可以使用附件中修改过的单元来解决字体问题。
关于“如何在xml某节点处加入另一个xml文件的内容?”的问题,您可以先创建一个临时的 XMLDocument 并装载源文件,再使用 OmniXMLUtils 单元提供的 CopyNode 函数把源 XML 的do
cumentElement 节点复制到目标节点。
 
好啦,散分~
 
后退
顶部