我们的项目使用MSXML 6.0
com对象来处理XML
到ComImport
属性。低于com类提供访问现有MSXML COM
(我只留下SelectNodes澄清问题)。MSXMLl 6.0 XmlDOMNodeList在调用时失败GetEnumerator
[ComImport]
[ComSourceInterfaces("MSXML2.XMLDOMDocumentEvents")]
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("88d96a06-f192-11d4-a65f-0040963251e5")]
public class FreeThreadedDOMDocumentClass : IXMLDOMDocument2
{
[return: MarshalAs(UnmanagedType.Interface)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(0x1d)]
public extern object SelectNodes([In, MarshalAs(UnmanagedType.BStr)] string queryString);
}
[ComImport, Guid("2933BF95-7B36-11D2-B20E-00C04F983E60"), TypeLibType((short)0x10c0)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IXMLDOMDocument2
{
[return: MarshalAs(UnmanagedType.Interface)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(0x1d)]
object SelectNodes([In, MarshalAs(UnmanagedType.BStr)] string queryString);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix"), ComImport]
[Guid("2933BF82-7B36-11D2-B20E-00C04F983E60")]
[TypeLibType(TypeLibTypeFlags.FDispatchable)]//(short) 0x10c0
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IXMLDOMNodeList: IEnumerable
{
[DispId(0)]
IXMLDOMNode this[int index]
{
[return: MarshalAs(UnmanagedType.Interface)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0)]
get;
}
[DispId(0x4a)]
int Count
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0x4a)]
get;
}
}
而且我们有一些代码部分的问题。例如:
string xmlText = "<Item> <Element></Element></Item>";
IXMLDOMDocument2 domDocument = new FreeThreadedDOMDocumentClass();
domDocument.LoadXml(xmlText);
string xPath = "//Item";
IXMLDOMNodeList resultQuery = domDocument.SelectNodes(xPath) as IXMLDOMNodeList;
resultQuery.GetEnumerator()
获得的对象resultQuery
作为SelectNodes
执行的结果与根据一些外部因素的GetEnumerator问题:
在视窗7或更早期的系统(系统没有支撑的WinRT技术的)
- 获得对象
resultQuery
具有类型System.__ComObject
- resultQuery.GetEnumerator()执行没有任何问题和提供工作枚举
- 获得对象
在窗口8个或更多更高版本的系统(与支持的WinRT技术的系统)
- 获得对象
resultQuery
具有类型Windows.Data.Xml.Dom.XmlNodeList
。这是WinRt类型。 - resultQuery.GetEnumerator()抛出异常:
System.ArgumentException: The object's type must not be a Windows Runtime type
。我想出了例外的来源是Marshal.GetComObjectData
。这意味着我们的编组过程失败
- 获得对象
在Windows 8或更晚的系统进口COM
MSXML 3.0
的版本:- 获得对象
resultQuery
已键入System.__ComObject
- resultQuery.GetEnumerator()的执行没有任何问题,并提供工作枚举
- 获得对象
这时,我发现了2点(使用与WinRT的窗户MSXML)三种解决方法,但不是解决方案为我们(可与相同的问题开发商是有帮助的):
- 不要使用的foreach和GetEnumerator的。它很明确:)
- 使用ICustomMarshaler创建
SelectNodes
的自定义编组,它将创建WinRT类型的包装并通过for
提供自定义GetEnumerator。 - MSXML的变化版本6至3
我需要帮助找到问题的根源在点2,了解如何解决它。 由于
Artsiom谢谢你打开它。我正在尝试使用MSXML 6来完成同样的事情(这对我来说不适用于MSXML 3)。我也试图遍历一组检索的节点。你的答案并不清晰,我希望我不必去解构DLL,添加到IXMLDOMNodeList。这似乎是比预期更深的方式,以避免当前MSXML版本中的问题。你有没有发现任何其他方法来编码?我在.NET框架中使用VBScript。谢谢。 – Dave