我們的項目使用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