MSXML - 命名空间信息不持久

时间:2010-10-07 14:48:42

标签: delphi msxml xslt

我正在使用MSXML 6.0将我自己的XML转换为另一种XML格式。我不确定我是否只是不明白MSXML究竟是如何工作的,但我相信我已经注意到它有一些奇怪的行为....

我使用setProperty方法将名称空间添加到我的XML文档中,例如

XmlDocument.setProperty('SelectionNamespaces',
' xmlns:ms=''http://mydomain.com/2010/MySchema''');

然后我在内存中使用自己的自定义序列化程序构建XML(不保存到磁盘)。一旦序列化,我然后加载XSLT文件并使用transformNodeToObject例如

执行转换
AppXmlDoc.transformNodeToObject(XslXmlDoc, AStreamForTransformedXml);

问题是转换正在运行,但我没有匹配XPath的特定模板。我通过Visual Studio运行测试数据来消除XSLT文件本身的任何问题,并且它按预期工作。然后我认为它一定是一个编码问题所以我确保所有涉及的文件都被读取/写出为UTF-8 ....仍然没有运气。

以下是转换的示例:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ms="http://mydomain.com/2010/MySchema" exclude-result-prefixes="ms">
<xsl:template match="/">
<ARoot>      
  <head>
    <xsl:apply-templates select="ms:Element/ms:SubElement" />
  </head>
  <body>
    <xsl:apply-templates select="ms:Element/ms:DifferentSubElement" />
  </body>
</ARoot>

因此,通过MSXML运行时的转换结果会带来基本结构,但不包含任何模板数据。经过一些测试后,我发现让它工作的唯一方法是按照以下步骤进行:

  1. 创建新的XML文档
  2. 使用setProperty
  3. 设置命名空间信息
  4. 序列化XML并保存到磁盘。
  5. 关闭文档 - 额外步骤
  6. 创建新的Xml文档 - 额外步骤
  7. 重新加载文档 - 额外步骤
  8. 重新设置命名空间信息 - 额外步骤
  9. 执行转换。
  10. 因此,似乎MSXML在某个点失去了对命名空间信息的跟踪。即使您重置命名空间信息(在序列化之后)并尝试转换它仍然不起作用,更令人感到奇怪的是什么!如果我保存文档,关闭它并重新创建一个新的XML文档并将其重新加载(这样我需要重置名称空间),它似乎才有效。

    有人对此有任何想法/想法吗?

1 个答案:

答案 0 :(得分:1)

使用selectNodes和selectSingleNode方法将SelectionNamespace property用于XPath,而不是用于XSLT或其他目的。所以我不确定你为什么设置它以及你希望它有什么帮助,因为你似乎没有使用selectNodes或selectSingleNode。 你想用MSXML 6实现什么?如果要在命名空间中创建一些包含元素和/或属性的MSXML DOM文档,请确保使用createNode,因为这是MSXML API中唯一的名称空间感知方法。