Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1092 lines
37 KiB

  1. Attribute VB_Name = "Main"
  2. Option Explicit
  3. Private Const FIRST_C As Long = 0
  4. Private Const SECOND_C As Long = 1
  5. Private p_dictStopWords(1) As Scripting.Dictionary
  6. Private p_dictHelpImage(1) As Scripting.Dictionary
  7. Private p_dictScopes(1) As Scripting.Dictionary
  8. Private p_dictFTS(1) As Scripting.Dictionary
  9. Private p_dictOperators(1) As Scripting.Dictionary
  10. Private p_dictStopSigns(1) As Scripting.Dictionary
  11. Private p_dictIndex(1) As Scripting.Dictionary
  12. Private p_dictSynTable(1) As Scripting.Dictionary
  13. Private p_dictTaxonomy(1) As Scripting.Dictionary
  14. Private p_intNumNodesAdd(1) As Long
  15. Private p_intNumNodesDel(1) As Long
  16. Private p_intNumTopicsAdd(1) As Long
  17. Private p_intNumTopicsDel(1) As Long
  18. Private p_intNumKeywords(1) As Long
  19. Private p_intNumKW As Long
  20. Private p_strCab1 As String
  21. Private p_strCab2 As String
  22. Private p_strHTMReport As String
  23. Public Sub MainFunction( _
  24. ByVal i_strCab1 As String, _
  25. ByVal i_strCab2 As String, _
  26. ByVal i_strHTMReport As String _
  27. )
  28. On Error GoTo LError
  29. Dim strFolder1 As String
  30. Dim strFolder2 As String
  31. Dim intErrorNumber As Long
  32. p_strCab1 = i_strCab1
  33. p_strCab2 = i_strCab2
  34. p_strHTMReport = i_strHTMReport
  35. strFolder1 = Cab2Folder(i_strCab1)
  36. strFolder2 = Cab2Folder(i_strCab2)
  37. p_GatherData FIRST_C, strFolder1
  38. p_GatherData SECOND_C, strFolder2
  39. p_Report
  40. LEnd:
  41. DeleteCabFolder strFolder1
  42. DeleteCabFolder strFolder2
  43. Exit Sub
  44. LError:
  45. frmMain.Output Err.Description, LOGGING_TYPE_ERROR_E
  46. intErrorNumber = Err.Number
  47. DeleteCabFolder strFolder1
  48. DeleteCabFolder strFolder2
  49. Err.Raise intErrorNumber
  50. End Sub
  51. Private Sub p_GatherData( _
  52. ByVal i_intIndex As Long, _
  53. ByVal i_strFolder As String _
  54. )
  55. Dim DOMDocPkgDesc As MSXML2.DOMDocument
  56. Dim intNumHHTs As Long
  57. Dim intIndex As Long
  58. Dim strFile As String
  59. Set p_dictStopWords(i_intIndex) = New Scripting.Dictionary
  60. Set p_dictHelpImage(i_intIndex) = New Scripting.Dictionary
  61. Set p_dictScopes(i_intIndex) = New Scripting.Dictionary
  62. Set p_dictFTS(i_intIndex) = New Scripting.Dictionary
  63. Set p_dictOperators(i_intIndex) = New Scripting.Dictionary
  64. Set p_dictStopSigns(i_intIndex) = New Scripting.Dictionary
  65. Set p_dictIndex(i_intIndex) = New Scripting.Dictionary
  66. Set p_dictSynTable(i_intIndex) = New Scripting.Dictionary
  67. Set p_dictTaxonomy(i_intIndex) = New Scripting.Dictionary
  68. p_intNumNodesAdd(i_intIndex) = 0
  69. p_intNumNodesDel(i_intIndex) = 0
  70. p_intNumTopicsAdd(i_intIndex) = 0
  71. p_intNumTopicsDel(i_intIndex) = 0
  72. p_intNumKeywords(i_intIndex) = 0
  73. p_intNumKW = 0
  74. Set DOMDocPkgDesc = GetPackageDescription(i_strFolder)
  75. intNumHHTs = GetNumberOfHHTsListedInPackageDescription(DOMDocPkgDesc)
  76. For intIndex = 1 To intNumHHTs
  77. strFile = GetNthHHTListedInPackageDescription(DOMDocPkgDesc, intIndex)
  78. p_ReadFile i_intIndex, i_strFolder, strFile
  79. Next
  80. End Sub
  81. Private Sub p_ReadFile( _
  82. ByVal i_intIndex As Long, _
  83. ByVal i_strFolder As String, _
  84. ByVal i_strFile As String _
  85. )
  86. Dim strLocation As String
  87. Dim strPath As String
  88. Dim DOMDoc As MSXML2.DOMDocument
  89. If (i_intIndex = FIRST_C) Then
  90. strLocation = " in first CAB"
  91. Else
  92. strLocation = " in second CAB"
  93. End If
  94. frmMain.Output "Processing " & i_strFile & strLocation & "...", LOGGING_TYPE_NORMAL_E
  95. strPath = i_strFolder & "\" & i_strFile
  96. Set DOMDoc = GetFileAsDomDocument(strPath)
  97. p_GetNumNodesTopicsKeywords i_intIndex, DOMDoc
  98. p_ReadStopWords i_intIndex, DOMDoc
  99. p_ReadHelpImage i_intIndex, DOMDoc
  100. p_ReadScopes i_intIndex, DOMDoc
  101. p_ReadFTS i_intIndex, DOMDoc
  102. p_ReadOperators i_intIndex, DOMDoc
  103. p_ReadStopSigns i_intIndex, DOMDoc
  104. p_ReadIndex i_intIndex, DOMDoc
  105. p_ReadSynTable i_intIndex, DOMDoc
  106. p_ReadTaxonomy i_intIndex, DOMDoc
  107. End Sub
  108. Private Sub p_GetNumNodesTopicsKeywords( _
  109. ByVal i_intIndex As Long, _
  110. ByVal i_DOMDoc As MSXML2.DOMDocument _
  111. )
  112. Dim DOMNodeList As MSXML2.IXMLDOMNodeList
  113. i_DOMDoc.setProperty "SelectionLanguage", "XPath"
  114. Set DOMNodeList = i_DOMDoc.selectNodes("//TAXONOMY_ENTRY[@ENTRY and @ACTION='ADD']")
  115. p_intNumNodesAdd(i_intIndex) = p_intNumNodesAdd(i_intIndex) + DOMNodeList.length
  116. Set DOMNodeList = i_DOMDoc.selectNodes("//TAXONOMY_ENTRY[@ENTRY and @ACTION='DEL']")
  117. p_intNumNodesDel(i_intIndex) = p_intNumNodesDel(i_intIndex) + DOMNodeList.length
  118. Set DOMNodeList = i_DOMDoc.selectNodes("//TAXONOMY_ENTRY[not(@ENTRY) and @ACTION='ADD']")
  119. p_intNumTopicsAdd(i_intIndex) = p_intNumTopicsAdd(i_intIndex) + DOMNodeList.length
  120. Set DOMNodeList = i_DOMDoc.selectNodes("//TAXONOMY_ENTRY[not(@ENTRY) and @ACTION='DEL']")
  121. p_intNumTopicsDel(i_intIndex) = p_intNumTopicsDel(i_intIndex) + DOMNodeList.length
  122. Set DOMNodeList = i_DOMDoc.selectNodes("//TAXONOMY_ENTRY[not(@ENTRY) and @ACTION='ADD']/KEYWORD")
  123. p_intNumKeywords(i_intIndex) = p_intNumKeywords(i_intIndex) + DOMNodeList.length
  124. End Sub
  125. Private Sub p_ReadStopWords( _
  126. ByVal i_intIndex As Long, _
  127. ByVal i_DOMDoc As MSXML2.DOMDocument _
  128. )
  129. Dim DOMNodeList As MSXML2.IXMLDOMNodeList
  130. Dim DOMNode As MSXML2.IXMLDOMNode
  131. Dim strStopWord As String
  132. Dim strAction As String
  133. Dim strOldAction As String
  134. Set DOMNodeList = i_DOMDoc.selectNodes("METADATA/STOPWORD_ENTRIES/STOPWORD")
  135. For Each DOMNode In DOMNodeList
  136. DoEvents
  137. strAction = UCase$(p_GetAttribute(DOMNode, "ACTION"))
  138. strStopWord = UCase$(p_GetAttribute(DOMNode, "STOPWORD"))
  139. p_CheckAction "StopWord " & strStopWord, strAction
  140. If (Not p_dictStopWords(i_intIndex).Exists(strStopWord)) Then
  141. p_dictStopWords(i_intIndex).Add strStopWord, strAction
  142. Else
  143. strOldAction = p_dictStopWords(i_intIndex)(strStopWord)
  144. If (strOldAction <> strAction) Then
  145. Err.Raise E_FAIL, , _
  146. "StopWord " & strStopWord & " has incompatible actions: " & _
  147. strOldAction & " & " & strAction
  148. End If
  149. End If
  150. Next
  151. End Sub
  152. Private Sub p_ReadHelpImage( _
  153. ByVal i_intIndex As Long, _
  154. ByVal i_DOMDoc As MSXML2.DOMDocument _
  155. )
  156. Dim DOMNodeList As MSXML2.IXMLDOMNodeList
  157. Dim DOMNode As MSXML2.IXMLDOMNode
  158. Dim strChm As String
  159. Dim strAction As String
  160. Dim strOldAction As String
  161. Set DOMNodeList = i_DOMDoc.selectNodes("METADATA/HELPIMAGE/HELPFILE")
  162. For Each DOMNode In DOMNodeList
  163. DoEvents
  164. strAction = UCase$(p_GetAttribute(DOMNode, "ACTION"))
  165. strChm = UCase$(p_GetAttribute(DOMNode, "CHM"))
  166. p_CheckAction "HelpFile " & strChm, strAction
  167. If (Not p_dictHelpImage(i_intIndex).Exists(strChm)) Then
  168. p_dictHelpImage(i_intIndex).Add strChm, strAction
  169. Else
  170. strOldAction = p_dictHelpImage(i_intIndex)(strChm)
  171. If (strOldAction <> strAction) Then
  172. Err.Raise E_FAIL, , _
  173. "HelpFile " & strChm & " has incompatible actions: " & _
  174. strOldAction & " & " & strAction
  175. End If
  176. End If
  177. Next
  178. End Sub
  179. Private Sub p_ReadScopes( _
  180. ByVal i_intIndex As Long, _
  181. ByVal i_DOMDoc As MSXML2.DOMDocument _
  182. )
  183. Dim DOMNodeList As MSXML2.IXMLDOMNodeList
  184. Dim DOMNode As MSXML2.IXMLDOMNode
  185. Dim strId As String
  186. Dim strAction As String
  187. Dim strOldAction As String
  188. Set DOMNodeList = i_DOMDoc.selectNodes("METADATA/SCOPE_DEFINITION/SCOPE")
  189. For Each DOMNode In DOMNodeList
  190. DoEvents
  191. strAction = UCase$(p_GetAttribute(DOMNode, "ACTION"))
  192. strId = UCase$(p_GetAttribute(DOMNode, "ID"))
  193. p_CheckAction "Scope " & strId, strAction
  194. If (Not p_dictScopes(i_intIndex).Exists(strId)) Then
  195. p_dictScopes(i_intIndex).Add strId, strAction
  196. Else
  197. strOldAction = p_dictScopes(i_intIndex)(strId)
  198. If (strOldAction <> strAction) Then
  199. Err.Raise E_FAIL, , _
  200. "Scope " & strId & " has incompatible actions: " & _
  201. strOldAction & " & " & strAction
  202. End If
  203. End If
  204. Next
  205. End Sub
  206. Private Sub p_ReadFTS( _
  207. ByVal i_intIndex As Long, _
  208. ByVal i_DOMDoc As MSXML2.DOMDocument _
  209. )
  210. Dim DOMNodeList As MSXML2.IXMLDOMNodeList
  211. Dim DOMNode As MSXML2.IXMLDOMNode
  212. Dim strAction As String
  213. Dim strChm As String
  214. Dim strChq As String
  215. Dim strKey As String
  216. Dim strOldAction As String
  217. Set DOMNodeList = i_DOMDoc.selectNodes("METADATA/FTS/HELPFILE")
  218. For Each DOMNode In DOMNodeList
  219. DoEvents
  220. strAction = UCase$(p_GetAttribute(DOMNode, "ACTION"))
  221. strChm = UCase$(p_GetAttribute(DOMNode, "CHM"))
  222. strChq = UCase$(p_GetAttribute(DOMNode, "CHQ", False))
  223. strKey = strChm & "/" & strChq
  224. p_CheckAction "FTS file " & strKey, strAction
  225. If (Not p_dictFTS(i_intIndex).Exists(strKey)) Then
  226. p_dictFTS(i_intIndex).Add strKey, strAction
  227. Else
  228. strOldAction = p_dictFTS(i_intIndex)(strKey)
  229. If (strOldAction <> strAction) Then
  230. Err.Raise E_FAIL, , _
  231. "FTS file " & strKey & " has incompatible actions: " & _
  232. strOldAction & " & " & strAction
  233. End If
  234. End If
  235. Next
  236. End Sub
  237. Private Sub p_ReadOperators( _
  238. ByVal i_intIndex As Long, _
  239. ByVal i_DOMDoc As MSXML2.DOMDocument _
  240. )
  241. Dim DOMNodeList As MSXML2.IXMLDOMNodeList
  242. Dim DOMNode As MSXML2.IXMLDOMNode
  243. Dim strOperator As String
  244. Dim strAction As String
  245. Dim strOperation As String
  246. Dim strItem As String
  247. Dim strOldItem As String
  248. Set DOMNodeList = i_DOMDoc.selectNodes("METADATA/OPERATOR_ENTRIES/OPERATOR")
  249. For Each DOMNode In DOMNodeList
  250. DoEvents
  251. strAction = UCase$(p_GetAttribute(DOMNode, "ACTION"))
  252. strOperation = UCase$(p_GetAttribute(DOMNode, "OPERATION"))
  253. strOperator = UCase$(p_GetAttribute(DOMNode, "OPERATOR"))
  254. strItem = strAction & "/" & strOperation
  255. p_CheckAction "Operator " & strOperator, strAction
  256. p_CheckOperation "Operator " & strOperator, strOperation
  257. If (Not p_dictOperators(i_intIndex).Exists(strOperator)) Then
  258. p_dictOperators(i_intIndex).Add strOperator, strItem
  259. Else
  260. strOldItem = p_dictOperators(i_intIndex)(strOperator)
  261. If (strOldItem <> strItem) Then
  262. Err.Raise E_FAIL, , _
  263. "Operator " & strOperator & " has incompatible definitions: " & _
  264. strOldItem & " and " & strItem
  265. End If
  266. End If
  267. Next
  268. End Sub
  269. Private Sub p_ReadStopSigns( _
  270. ByVal i_intIndex As Long, _
  271. ByVal i_DOMDoc As MSXML2.DOMDocument _
  272. )
  273. Dim DOMNodeList As MSXML2.IXMLDOMNodeList
  274. Dim DOMNode As MSXML2.IXMLDOMNode
  275. Dim strAction As String
  276. Dim strContext As String
  277. Dim strStopSign As String
  278. Dim strItem As String
  279. Dim strOldItem As String
  280. Set DOMNodeList = i_DOMDoc.selectNodes("METADATA/STOPSIGN_ENTRIES/STOPSIGN")
  281. For Each DOMNode In DOMNodeList
  282. DoEvents
  283. strAction = UCase$(p_GetAttribute(DOMNode, "ACTION"))
  284. strContext = UCase$(p_GetAttribute(DOMNode, "CONTEXT"))
  285. strStopSign = UCase$(p_GetAttribute(DOMNode, "STOPSIGN"))
  286. strItem = strAction & "/" & strContext
  287. p_CheckAction "StopSign " & strStopSign, strAction
  288. p_CheckContext "StopSign " & strStopSign, strContext
  289. If (Not p_dictStopSigns(i_intIndex).Exists(strStopSign)) Then
  290. p_dictStopSigns(i_intIndex).Add strStopSign, strItem
  291. Else
  292. strOldItem = p_dictStopSigns(i_intIndex)(strStopSign)
  293. If (strOldItem <> strItem) Then
  294. Err.Raise E_FAIL, , _
  295. "StopSign " & strStopSign & " has incompatible definitions: " & _
  296. strOldItem & " and " & strItem
  297. End If
  298. End If
  299. Next
  300. End Sub
  301. Private Sub p_ReadIndex( _
  302. ByVal i_intIndex As Long, _
  303. ByVal i_DOMDoc As MSXML2.DOMDocument _
  304. )
  305. Dim DOMNodeList As MSXML2.IXMLDOMNodeList
  306. Dim DOMNode As MSXML2.IXMLDOMNode
  307. Dim strAction As String
  308. Dim strChm As String
  309. Dim strHhk As String
  310. Dim strScope As String
  311. Dim strKey As String
  312. Dim strItem As String
  313. Dim strOldItem As String
  314. Set DOMNodeList = i_DOMDoc.selectNodes("METADATA/INDEX/HELPFILE")
  315. For Each DOMNode In DOMNodeList
  316. DoEvents
  317. strAction = UCase$(p_GetAttribute(DOMNode, "ACTION"))
  318. strChm = UCase$(p_GetAttribute(DOMNode, "CHM"))
  319. strHhk = UCase$(p_GetAttribute(DOMNode, "HHK"))
  320. strScope = UCase$(p_GetAttribute(DOMNode, "SCOPE", False))
  321. strKey = strChm & strHhk
  322. strItem = strAction & "/" & strScope
  323. p_CheckAction "Index " & strKey, strAction
  324. If (Not p_dictIndex(i_intIndex).Exists(strKey)) Then
  325. p_dictIndex(i_intIndex).Add strKey, strItem
  326. Else
  327. strOldItem = p_dictIndex(i_intIndex)(strKey)
  328. If (strOldItem <> strItem) Then
  329. Err.Raise E_FAIL, , _
  330. "Index " & strKey & " has incompatible definitions: " & _
  331. strOldItem & " and " & strItem
  332. End If
  333. End If
  334. Next
  335. End Sub
  336. Private Sub p_ReadSynTable( _
  337. ByVal i_intIndex As Long, _
  338. ByVal i_DOMDoc As MSXML2.DOMDocument _
  339. )
  340. Dim DOMNodeSynSetList As MSXML2.IXMLDOMNodeList
  341. Dim DOMNodeSynonymList As MSXML2.IXMLDOMNodeList
  342. Dim DOMNodeSynSet As MSXML2.IXMLDOMNode
  343. Dim DOMNodeSynonym As MSXML2.IXMLDOMNode
  344. Dim dict As Scripting.Dictionary
  345. Dim strId As String
  346. Dim strSynonym As String
  347. Dim strAction As String
  348. Dim strOldAction As String
  349. Set DOMNodeSynSetList = i_DOMDoc.selectNodes("METADATA/SYNTABLE/SYNSET")
  350. For Each DOMNodeSynSet In DOMNodeSynSetList
  351. DoEvents
  352. strId = UCase$(p_GetAttribute(DOMNodeSynSet, "ID"))
  353. If (p_dictSynTable(i_intIndex).Exists(strId)) Then
  354. Set dict = p_dictSynTable(i_intIndex)(strId)
  355. Else
  356. Set dict = New Scripting.Dictionary
  357. p_dictSynTable(i_intIndex).Add strId, dict
  358. End If
  359. Set DOMNodeSynonymList = DOMNodeSynSet.selectNodes("SYNONYM")
  360. For Each DOMNodeSynonym In DOMNodeSynonymList
  361. DoEvents
  362. strSynonym = UCase$(DOMNodeSynonym.Text)
  363. strAction = UCase$(p_GetAttribute(DOMNodeSynonym, "ACTION"))
  364. p_CheckAction "SynSet " & strId & ": " & "Synonym " & strSynonym, strAction
  365. If (Not dict.Exists(strSynonym)) Then
  366. dict.Add strSynonym, strAction
  367. Else
  368. strOldAction = dict(strSynonym)
  369. If (strOldAction <> strAction) Then
  370. Err.Raise E_FAIL, , _
  371. "SynSet " & strId & ": " & "Synonym " & strSynonym & " has incompatible actions: " & _
  372. strOldAction & " & " & strAction
  373. End If
  374. End If
  375. Next
  376. Next
  377. End Sub
  378. Private Sub p_ReadTaxonomy( _
  379. ByVal i_intIndex As Long, _
  380. ByVal i_DOMDoc As MSXML2.DOMDocument _
  381. )
  382. Dim DOMNodeList As MSXML2.IXMLDOMNodeList
  383. Dim DOMNode As MSXML2.IXMLDOMNode
  384. Dim DOMNodeListKW As MSXML2.IXMLDOMNodeList
  385. Dim DOMNodeKW As MSXML2.IXMLDOMNode
  386. Dim strCategory As String
  387. Dim strEntry As String
  388. Dim strURI As String
  389. Dim strKey As String
  390. Dim intNumKW As Long
  391. Set DOMNodeList = i_DOMDoc.selectNodes("METADATA/TAXONOMY_ENTRIES/TAXONOMY_ENTRY")
  392. For Each DOMNode In DOMNodeList
  393. DoEvents
  394. strCategory = UCase$(p_GetAttribute(DOMNode, "CATEGORY"))
  395. strEntry = UCase$(p_GetAttribute(DOMNode, "ENTRY", False))
  396. strURI = UCase$(p_GetAttribute(DOMNode, "URI", False))
  397. strKey = "CATEGORY: " & strCategory & ";" & _
  398. "ENTRY: " & strEntry & ";" & _
  399. "URI: " & strURI & ";"
  400. Set DOMNodeListKW = DOMNode.selectNodes("KEYWORD")
  401. intNumKW = DOMNodeListKW.length
  402. For Each DOMNodeKW In DOMNodeListKW
  403. DOMNode.removeChild DOMNodeKW
  404. Next
  405. If (Not p_dictTaxonomy(i_intIndex).Exists(strKey)) Then
  406. p_dictTaxonomy(i_intIndex).Add strKey, DOMNode
  407. p_intNumKW = p_intNumKW + intNumKW
  408. Else
  409. Err.Raise E_FAIL, , "Taxonomy entry """ & strKey & """ is defined twice"
  410. End If
  411. Next
  412. End Sub
  413. Private Sub p_Report()
  414. Dim intSet1 As Long
  415. Dim intAdd1 As Long
  416. Dim intDel1 As Long
  417. Dim intSet2 As Long
  418. Dim intAdd2 As Long
  419. Dim intDel2 As Long
  420. Dim str As String
  421. Dim strHTM As String
  422. Dim bln As Boolean
  423. Dim intExtraHHKsInFirstCab As Long
  424. strHTM = "<html><head><title>LocDiff report of " & Date & " " & Time & "</title></head><body>"
  425. frmMain.Output vbCrLf & "1st CAB: " & p_strCab1, LOGGING_TYPE_NORMAL_E
  426. frmMain.Output "2nd CAB: " & p_strCab2 & vbCrLf, LOGGING_TYPE_NORMAL_E
  427. strHTM = strHTM & "Reference (1st) CAB: " & p_strCab1 & "<BR>"
  428. strHTM = strHTM & "Localized (2nd) CAB: " & p_strCab2 & "<BR><BR>"
  429. strHTM = strHTM & "<table border='1'>" & _
  430. "<tr><td>&nbsp;</td><td>&nbsp;</td><td>Reference CAB</font></td><td>Localized CAB</td></tr>"
  431. frmMain.Output "StopWords:", LOGGING_TYPE_NORMAL_E
  432. p_GetActionStats p_dictStopWords(FIRST_C), intAdd1, intDel1, p_dictStopWords(SECOND_C), intAdd2, intDel2
  433. frmMain.Output vbTab & "1st CAB: ADDs: " & intAdd1 & "; DELs: " & intDel1, LOGGING_TYPE_NORMAL_E
  434. frmMain.Output vbTab & "2nd CAB: ADDs: " & intAdd2 & "; DELs: " & intDel2, LOGGING_TYPE_NORMAL_E
  435. strHTM = strHTM & "<tr>" & _
  436. p_GetHTMRow("StopWords", "ADDs", intAdd1, intAdd2) & _
  437. "</tr><tr>" & _
  438. p_GetHTMRow("&nbsp;", "DELs", intDel1, intDel2) & _
  439. "</tr>"
  440. frmMain.Output "StopSigns:", LOGGING_TYPE_NORMAL_E
  441. p_GetActionStats p_dictStopSigns(FIRST_C), intAdd1, intDel1, p_dictStopSigns(SECOND_C), intAdd2, intDel2
  442. frmMain.Output vbTab & "1st CAB: ADDs: " & intAdd1 & "; DELs: " & intDel1, LOGGING_TYPE_NORMAL_E
  443. frmMain.Output vbTab & "2nd CAB: ADDs: " & intAdd2 & "; DELs: " & intDel2, LOGGING_TYPE_NORMAL_E
  444. strHTM = strHTM & "<tr>" & _
  445. p_GetHTMRow("StopSigns", "ADDs", intAdd1, intAdd2) & _
  446. "</tr><tr>" & _
  447. p_GetHTMRow("&nbsp;", "DELs", intDel1, intDel2) & _
  448. "</tr>"
  449. frmMain.Output "Operators:", LOGGING_TYPE_NORMAL_E
  450. p_GetActionStats p_dictOperators(FIRST_C), intAdd1, intDel1, p_dictOperators(SECOND_C), intAdd2, intDel2
  451. frmMain.Output vbTab & "1st CAB: ADDs: " & intAdd1 & "; DELs: " & intDel1, LOGGING_TYPE_NORMAL_E
  452. frmMain.Output vbTab & "2nd CAB: ADDs: " & intAdd2 & "; DELs: " & intDel2, LOGGING_TYPE_NORMAL_E
  453. strHTM = strHTM & "<tr>" & _
  454. p_GetHTMRow("Operators", "ADDs", intAdd1, intAdd2) & _
  455. "</tr><tr>" & _
  456. p_GetHTMRow("&nbsp;", "DELs", intDel1, intDel2) & _
  457. "</tr>"
  458. frmMain.Output "Synonym Table:", LOGGING_TYPE_NORMAL_E
  459. p_GetSynonymStats p_dictSynTable(FIRST_C), intSet1, intAdd1, intDel1, p_dictSynTable(SECOND_C), intSet2, intAdd2, intDel2
  460. frmMain.Output vbTab & "1st CAB: Keyword ADDs: " & intAdd1 & "; Keyword DELs: " & intDel1 & "; sets: " & intSet1, LOGGING_TYPE_NORMAL_E
  461. frmMain.Output vbTab & "2nd CAB: Keyword ADDs: " & intAdd2 & "; Keyword DELs: " & intDel2 & "; sets: " & intSet2, LOGGING_TYPE_NORMAL_E
  462. strHTM = strHTM & "<tr>" & _
  463. p_GetHTMRow("Synonym Table", "Sets", intSet1, intSet2) & _
  464. "</tr><tr>" & _
  465. p_GetHTMRow("&nbsp;", "Keyword ADDs", intAdd1, intAdd2) & _
  466. "</tr><tr>" & _
  467. p_GetHTMRow("&nbsp;", "Keyword DELs", intDel1, intDel2) & _
  468. "</tr>"
  469. frmMain.Output "Nodes:", LOGGING_TYPE_NORMAL_E
  470. frmMain.Output vbTab & "1st CAB: ADDs: " & p_intNumNodesAdd(FIRST_C) & "; DELs: " & p_intNumNodesDel(FIRST_C), LOGGING_TYPE_NORMAL_E
  471. frmMain.Output vbTab & "2nd CAB: ADDs: " & p_intNumNodesAdd(SECOND_C) & "; DELs: " & p_intNumNodesDel(SECOND_C), LOGGING_TYPE_NORMAL_E
  472. strHTM = strHTM & "<tr>" & _
  473. p_GetHTMRow("Nodes", "ADDs", p_intNumNodesAdd(FIRST_C), p_intNumNodesAdd(SECOND_C)) & _
  474. "</tr><tr>" & _
  475. p_GetHTMRow("&nbsp;", "DELs", p_intNumNodesDel(FIRST_C), p_intNumNodesDel(SECOND_C)) & _
  476. "</tr>"
  477. frmMain.Output "Topics:", LOGGING_TYPE_NORMAL_E
  478. frmMain.Output vbTab & "1st CAB: ADDs: " & p_intNumTopicsAdd(FIRST_C) & "; DELs: " & p_intNumTopicsDel(FIRST_C), LOGGING_TYPE_NORMAL_E
  479. frmMain.Output vbTab & "2nd CAB: ADDs: " & p_intNumTopicsAdd(SECOND_C) & "; DELs: " & p_intNumTopicsDel(SECOND_C), LOGGING_TYPE_NORMAL_E
  480. strHTM = strHTM & "<tr>" & _
  481. p_GetHTMRow("Topics", "ADDs", p_intNumTopicsAdd(FIRST_C), p_intNumTopicsAdd(SECOND_C)) & _
  482. "</tr><tr>" & _
  483. p_GetHTMRow("&nbsp;", "DELs", p_intNumTopicsDel(FIRST_C), p_intNumTopicsDel(SECOND_C)) & _
  484. "</tr>"
  485. frmMain.Output "Keywords:", LOGGING_TYPE_NORMAL_E
  486. frmMain.Output vbTab & "1st CAB: ADDs: " & p_intNumKeywords(FIRST_C), LOGGING_TYPE_NORMAL_E
  487. frmMain.Output vbTab & "2nd CAB: ADDs: " & p_intNumKeywords(SECOND_C), LOGGING_TYPE_NORMAL_E
  488. strHTM = strHTM & "<tr>" & _
  489. p_GetHTMRow("Keywords", "ADDs", p_intNumKeywords(FIRST_C), p_intNumKeywords(SECOND_C)) & _
  490. "</tr>"
  491. strHTM = strHTM & "</table>"
  492. frmMain.Output "HelpImage:", LOGGING_TYPE_NORMAL_E
  493. bln = p_Identical("HelpImage", p_dictHelpImage(FIRST_C), p_dictHelpImage(SECOND_C), str)
  494. If (Not bln) Then
  495. frmMain.Output vbTab & "!!!Comparison failed!!!", LOGGING_TYPE_NORMAL_E
  496. frmMain.Output vbTab & p_InsertTabs(str), LOGGING_TYPE_NORMAL_E
  497. Else
  498. frmMain.Output vbTab & "Identical", LOGGING_TYPE_NORMAL_E
  499. End If
  500. strHTM = strHTM & "<br>" & p_GetHTMTable("HelpImage", bln, str)
  501. frmMain.Output "Scopes:", LOGGING_TYPE_NORMAL_E
  502. bln = p_Identical("Scope", p_dictScopes(FIRST_C), p_dictScopes(SECOND_C), str)
  503. If (Not bln) Then
  504. frmMain.Output vbTab & "!!!Comparison failed!!!", LOGGING_TYPE_NORMAL_E
  505. frmMain.Output vbTab & p_InsertTabs(str), LOGGING_TYPE_NORMAL_E
  506. Else
  507. frmMain.Output vbTab & "Identical", LOGGING_TYPE_NORMAL_E
  508. End If
  509. strHTM = strHTM & "<br>" & p_GetHTMTable("Scopes", bln, str)
  510. frmMain.Output "Index:", LOGGING_TYPE_NORMAL_E
  511. bln = p_Identical("Index", p_dictIndex(FIRST_C), p_dictIndex(SECOND_C), str)
  512. If (Not bln) Then
  513. frmMain.Output vbTab & "!!!Comparison failed!!!", LOGGING_TYPE_NORMAL_E
  514. frmMain.Output vbTab & p_InsertTabs(str), LOGGING_TYPE_NORMAL_E
  515. Else
  516. frmMain.Output vbTab & "Identical", LOGGING_TYPE_NORMAL_E
  517. End If
  518. strHTM = strHTM & "<br>" & p_GetHTMTable("Index", bln, str)
  519. frmMain.Output "FTS:", LOGGING_TYPE_NORMAL_E
  520. bln = p_Identical("FTS", p_dictFTS(FIRST_C), p_dictFTS(SECOND_C), str)
  521. If (Not bln) Then
  522. frmMain.Output vbTab & "!!!Comparison failed!!!", LOGGING_TYPE_NORMAL_E
  523. frmMain.Output vbTab & p_InsertTabs(str), LOGGING_TYPE_NORMAL_E
  524. Else
  525. frmMain.Output vbTab & "Identical", LOGGING_TYPE_NORMAL_E
  526. End If
  527. strHTM = strHTM & "<br>" & p_GetHTMTable("FTS", bln, str)
  528. frmMain.Output "Taxonomy:", LOGGING_TYPE_NORMAL_E
  529. bln = p_IdenticalTaxonomy(str, intExtraHHKsInFirstCab)
  530. If (Not bln) Then
  531. frmMain.Output vbTab & "!!!Comparison failed!!!", LOGGING_TYPE_NORMAL_E
  532. frmMain.Output vbTab & p_InsertTabs(str), LOGGING_TYPE_NORMAL_E
  533. Else
  534. frmMain.Output vbTab & "Identical", LOGGING_TYPE_NORMAL_E
  535. If (intExtraHHKsInFirstCab > 0) Then
  536. str = "The 1st CAB has " & intExtraHHKsInFirstCab & " extra HHK entries"
  537. ElseIf (intExtraHHKsInFirstCab < 0) Then
  538. str = "The 2nd CAB has " & intExtraHHKsInFirstCab * (-1) & " extra HHK entries"
  539. Else
  540. str = "The 2 CABs have the same number of HHK entries"
  541. End If
  542. frmMain.Output vbTab & str, LOGGING_TYPE_NORMAL_E
  543. End If
  544. strHTM = strHTM & "<br>" & p_GetHTMTable("Taxonomy", bln, str)
  545. strHTM = strHTM & "</body></html>"
  546. If (p_strHTMReport <> "") Then
  547. FileWrite p_strHTMReport, strHTM, , True
  548. End If
  549. End Sub
  550. Private Function p_GetHTMRow( _
  551. ByVal i_str1 As String, _
  552. ByVal i_str2 As String, _
  553. ByVal i_str3 As String, _
  554. ByVal i_str4 As String _
  555. ) As String
  556. p_GetHTMRow = "" & _
  557. "<td>" & i_str1 & "</td>" & _
  558. "<td>" & i_str2 & "</td>" & _
  559. "<td><p align='right'>" & i_str3 & "</td>" & _
  560. "<td><p align='right'>" & i_str4 & "</td>"
  561. End Function
  562. Private Function p_GetHTMTable( _
  563. ByVal i_strName As String, _
  564. ByVal i_blnSuccess As Boolean, _
  565. ByVal i_strNotes As String _
  566. ) As String
  567. Dim str As String
  568. If (i_blnSuccess) Then
  569. str = "" & _
  570. "<table border='1'>" & _
  571. "<tr>" & _
  572. "<td>" & i_strName & ":&nbsp<font color='#00FF00'><b>Identical</b></font></td>" & _
  573. "</tr>"
  574. If (i_strNotes <> "") Then
  575. str = str & _
  576. "<tr>" & _
  577. "<td><ul><li>" & Replace$(i_strNotes, vbCrLf, "</li><li>") & "</li></ul></td>" & _
  578. "</tr>"
  579. End If
  580. str = str & _
  581. "</table>"
  582. Else
  583. str = "" & _
  584. "<table border='1'>" & _
  585. "<tr>" & _
  586. "<td>" & i_strName & ":&nbsp<font color='#FF0000'><b>!!!Comparison failed!!!</b></font></td>" & _
  587. "</tr>" & _
  588. "<tr>" & _
  589. "<td><ul><li>" & Replace$(i_strNotes, vbCrLf, "</li><li>") & "</li></ul></td>" & _
  590. "</tr>" & _
  591. "</table>"
  592. End If
  593. p_GetHTMTable = str
  594. End Function
  595. Private Sub p_CheckAction( _
  596. ByVal i_strPrefix As String, _
  597. ByVal i_strAction As String _
  598. )
  599. If ((i_strAction <> "ADD") And (i_strAction <> "DEL")) Then
  600. Err.Raise E_FAIL, , i_strPrefix & ": Bad ACTION: " & i_strAction
  601. End If
  602. End Sub
  603. Private Sub p_CheckOperation( _
  604. ByVal i_strPrefix As String, _
  605. ByVal i_strOperation As String _
  606. )
  607. If ((i_strOperation <> "AND") And (i_strOperation <> "OR") And (i_strOperation <> "NOT")) Then
  608. Err.Raise E_FAIL, , i_strPrefix & ": Bad OPERATION: " & i_strOperation
  609. End If
  610. End Sub
  611. Private Sub p_CheckContext( _
  612. ByVal i_strPrefix As String, _
  613. ByVal i_strContext As String _
  614. )
  615. If ((i_strContext <> "ANYWHERE") And (i_strContext <> "ENDOFWORD")) Then
  616. Err.Raise E_FAIL, , i_strPrefix & ": Bad CONTEXT: " & i_strContext
  617. End If
  618. End Sub
  619. Private Function p_GetAttribute( _
  620. ByVal i_DOMNode As MSXML2.IXMLDOMNode, _
  621. ByVal i_strAttributeName As String, _
  622. Optional ByVal i_blnRequired As Boolean = True _
  623. ) As String
  624. Dim DOMAttribute As MSXML2.IXMLDOMAttribute
  625. Set DOMAttribute = i_DOMNode.Attributes.getNamedItem(i_strAttributeName)
  626. If (DOMAttribute Is Nothing) Then
  627. If (Not i_blnRequired) Then
  628. Exit Function
  629. Else
  630. Err.Raise E_FAIL, , "Attribute " & i_strAttributeName & " is missing in: " & i_DOMNode.xml
  631. End If
  632. End If
  633. p_GetAttribute = Replace$(DOMAttribute.Text, "\", "\\")
  634. End Function
  635. Private Function p_ExtractAttribute( _
  636. ByVal i_DOMElement As MSXML2.IXMLDOMElement, _
  637. ByVal i_strAttributeName As String _
  638. ) As String
  639. Dim DOMAttribute As MSXML2.IXMLDOMAttribute
  640. Set DOMAttribute = i_DOMElement.Attributes.getNamedItem(i_strAttributeName)
  641. If (Not (DOMAttribute Is Nothing)) Then
  642. p_ExtractAttribute = DOMAttribute.Text
  643. i_DOMElement.Attributes.removeNamedItem (i_strAttributeName)
  644. End If
  645. End Function
  646. Private Sub p_AppendStr( _
  647. ByRef u_str As String, _
  648. ByVal i_str As String _
  649. )
  650. If (u_str = "") Then
  651. u_str = i_str
  652. Else
  653. u_str = u_str & vbCrLf & i_str
  654. End If
  655. End Sub
  656. Private Function p_InsertTabs( _
  657. ByVal i_str As String _
  658. ) As String
  659. p_InsertTabs = Replace$(i_str, vbCrLf, vbCrLf & vbTab)
  660. End Function
  661. Private Sub p_GetActionStats( _
  662. ByRef i_dict1 As Scripting.Dictionary, _
  663. ByRef o_intAdd1 As Long, _
  664. ByRef o_intDel1 As Long, _
  665. ByRef i_dict2 As Scripting.Dictionary, _
  666. ByRef o_intAdd2 As Long, _
  667. ByRef o_intDel2 As Long _
  668. )
  669. Dim vntKey As Variant
  670. Dim strAction As String
  671. o_intAdd1 = 0
  672. o_intDel1 = 0
  673. o_intAdd2 = 0
  674. o_intDel2 = 0
  675. For Each vntKey In i_dict1.Keys
  676. DoEvents
  677. strAction = Mid$(i_dict1(vntKey), 1, 3)
  678. If (strAction = "ADD") Then
  679. o_intAdd1 = o_intAdd1 + 1
  680. ElseIf (strAction = "DEL") Then
  681. o_intDel1 = o_intDel1 + 1
  682. Else
  683. Err.Raise E_FAIL, , "Bad ACTION: " & strAction
  684. End If
  685. Next
  686. For Each vntKey In i_dict2.Keys
  687. DoEvents
  688. strAction = Mid$(i_dict2(vntKey), 1, 3)
  689. If (strAction = "ADD") Then
  690. o_intAdd2 = o_intAdd2 + 1
  691. ElseIf (strAction = "DEL") Then
  692. o_intDel2 = o_intDel2 + 1
  693. Else
  694. Err.Raise E_FAIL, , "Bad ACTION: " & strAction
  695. End If
  696. Next
  697. End Sub
  698. Private Sub p_GetSynonymStats( _
  699. ByRef i_dict1 As Scripting.Dictionary, _
  700. ByRef o_intSet1 As Long, _
  701. ByRef o_intAdd1 As Long, _
  702. ByRef o_intDel1 As Long, _
  703. ByRef i_dict2 As Scripting.Dictionary, _
  704. ByRef o_intSet2 As Long, _
  705. ByRef o_intAdd2 As Long, _
  706. ByRef o_intDel2 As Long _
  707. )
  708. Dim vntKey1 As Variant
  709. Dim vntKey2 As Variant
  710. Dim strAction As String
  711. o_intSet1 = i_dict1.Count
  712. o_intAdd1 = 0
  713. o_intDel1 = 0
  714. o_intSet2 = i_dict2.Count
  715. o_intAdd2 = 0
  716. o_intDel2 = 0
  717. For Each vntKey1 In i_dict1.Keys
  718. DoEvents
  719. For Each vntKey2 In i_dict1(vntKey1).Keys
  720. strAction = Mid$(i_dict1(vntKey1)(vntKey2), 1, 3)
  721. If (strAction = "ADD") Then
  722. o_intAdd1 = o_intAdd1 + 1
  723. ElseIf (strAction = "DEL") Then
  724. o_intDel1 = o_intDel1 + 1
  725. Else
  726. Err.Raise E_FAIL, , "Bad ACTION: " & strAction
  727. End If
  728. Next
  729. Next
  730. For Each vntKey1 In i_dict2.Keys
  731. DoEvents
  732. For Each vntKey2 In i_dict2(vntKey1).Keys
  733. strAction = Mid$(i_dict2(vntKey1)(vntKey2), 1, 3)
  734. If (strAction = "ADD") Then
  735. o_intAdd2 = o_intAdd2 + 1
  736. ElseIf (strAction = "DEL") Then
  737. o_intDel2 = o_intDel2 + 1
  738. Else
  739. Err.Raise E_FAIL, , "Bad ACTION: " & strAction
  740. End If
  741. Next
  742. Next
  743. End Sub
  744. Private Function p_Identical( _
  745. ByRef i_strName As String, _
  746. ByRef u_dict1 As Scripting.Dictionary, _
  747. ByRef u_dict2 As Scripting.Dictionary, _
  748. ByRef o_strOutput As String _
  749. ) As Boolean
  750. Dim vntKey As Variant
  751. Dim strItem1 As String
  752. Dim strItem2 As String
  753. Dim blnFailed As Boolean
  754. o_strOutput = ""
  755. For Each vntKey In u_dict1.Keys
  756. DoEvents
  757. If (Not u_dict2.Exists(vntKey)) Then
  758. p_AppendStr o_strOutput, i_strName & " " & vntKey & " exists only in the 1st CAB"
  759. blnFailed = True
  760. Else
  761. strItem1 = u_dict1(vntKey)
  762. strItem2 = u_dict2(vntKey)
  763. u_dict1.Remove vntKey
  764. u_dict2.Remove vntKey
  765. If (strItem1 <> strItem2) Then
  766. p_AppendStr o_strOutput, "Values of " & i_strName & " " & vntKey & " differ: " & _
  767. strItem1 & " & " & strItem2
  768. blnFailed = True
  769. End If
  770. End If
  771. Next
  772. For Each vntKey In u_dict2.Keys
  773. DoEvents
  774. If (Not u_dict1.Exists(vntKey)) Then
  775. p_AppendStr o_strOutput, i_strName & " " & vntKey & " exists only in the 2nd CAB"
  776. blnFailed = True
  777. End If
  778. Next
  779. p_Identical = Not blnFailed
  780. End Function
  781. Private Function p_IdenticalTaxonomy( _
  782. ByRef o_strOutput As String, _
  783. ByRef o_intExtraHHKsInFirstCab As Long _
  784. ) As Boolean
  785. Dim vntKey As Variant
  786. Dim DOMNodeItem1 As MSXML2.IXMLDOMNode
  787. Dim DOMNodeItem2 As MSXML2.IXMLDOMNode
  788. Dim blnFailed As Boolean
  789. Dim strCategory As String
  790. Dim str As String
  791. Dim intExtraHHKsInFirstCab As Long
  792. o_strOutput = ""
  793. For Each vntKey In p_dictTaxonomy(FIRST_C).Keys
  794. DoEvents
  795. Set DOMNodeItem1 = p_dictTaxonomy(FIRST_C)(vntKey)
  796. If (Not p_dictTaxonomy(SECOND_C).Exists(vntKey)) Then
  797. strCategory = p_GetAttribute(DOMNodeItem1, "CATEGORY", True)
  798. If (UCase$(Mid$(strCategory, 1, 4)) = "HHKS") Then
  799. intExtraHHKsInFirstCab = intExtraHHKsInFirstCab + 1
  800. Else
  801. p_AppendStr o_strOutput, "Taxonomy entry " & vntKey & " exists only in the 1st CAB"
  802. blnFailed = True
  803. End If
  804. Else
  805. Set DOMNodeItem2 = p_dictTaxonomy(SECOND_C)(vntKey)
  806. p_dictTaxonomy(FIRST_C).Remove vntKey
  807. p_dictTaxonomy(SECOND_C).Remove vntKey
  808. If (Not p_IdenticalTaxonomyEntries(DOMNodeItem1, DOMNodeItem2, str)) Then
  809. p_AppendStr o_strOutput, "Values of Taxonomy entry " & vntKey & " differ: " & str
  810. blnFailed = True
  811. End If
  812. End If
  813. Next
  814. For Each vntKey In p_dictTaxonomy(SECOND_C).Keys
  815. DoEvents
  816. Set DOMNodeItem2 = p_dictTaxonomy(SECOND_C)(vntKey)
  817. If (Not p_dictTaxonomy(FIRST_C).Exists(vntKey)) Then
  818. strCategory = p_GetAttribute(DOMNodeItem2, "CATEGORY", True)
  819. If (UCase$(Mid$(strCategory, 1, 4)) = "HHKS") Then
  820. intExtraHHKsInFirstCab = intExtraHHKsInFirstCab - 1
  821. Else
  822. p_AppendStr o_strOutput, "Taxonomy entry " & vntKey & " exists only in the 2nd CAB"
  823. blnFailed = True
  824. End If
  825. End If
  826. Next
  827. p_IdenticalTaxonomy = Not blnFailed
  828. o_intExtraHHKsInFirstCab = intExtraHHKsInFirstCab
  829. End Function
  830. Private Function p_IdenticalTaxonomyEntries( _
  831. ByVal u_DOMNode1 As MSXML2.IXMLDOMNode, _
  832. ByVal u_DOMNode2 As MSXML2.IXMLDOMNode, _
  833. ByRef o_strOutput As String _
  834. ) As Boolean
  835. ' Discard these localizable attributes
  836. p_ExtractAttribute u_DOMNode1, "TITLE"
  837. p_ExtractAttribute u_DOMNode2, "TITLE"
  838. p_ExtractAttribute u_DOMNode1, "DESCRIPTION"
  839. p_ExtractAttribute u_DOMNode2, "DESCRIPTION"
  840. ' Discard these attributes that form the key
  841. p_ExtractAttribute u_DOMNode1, "CATEGORY"
  842. p_ExtractAttribute u_DOMNode2, "CATEGORY"
  843. p_ExtractAttribute u_DOMNode1, "ENTRY"
  844. p_ExtractAttribute u_DOMNode2, "ENTRY"
  845. p_ExtractAttribute u_DOMNode1, "URI"
  846. p_ExtractAttribute u_DOMNode2, "URI"
  847. If (Not p_IdenticalAttributes("ICONURI", u_DOMNode1, u_DOMNode2, o_strOutput)) Then
  848. Exit Function
  849. End If
  850. If (Not p_IdenticalAttributes("TYPE", u_DOMNode1, u_DOMNode2, o_strOutput)) Then
  851. Exit Function
  852. End If
  853. If (Not p_IdenticalAttributes("VISIBLE", u_DOMNode1, u_DOMNode2, o_strOutput)) Then
  854. Exit Function
  855. End If
  856. If (Not p_IdenticalAttributes("ACTION", u_DOMNode1, u_DOMNode2, o_strOutput)) Then
  857. Exit Function
  858. End If
  859. If (Not p_IdenticalAttributes("INSERTMODE", u_DOMNode1, u_DOMNode2, o_strOutput)) Then
  860. Exit Function
  861. End If
  862. If (Not p_IdenticalAttributes("INSERTLOCATION", u_DOMNode1, u_DOMNode2, o_strOutput)) Then
  863. Exit Function
  864. End If
  865. If (Not p_IdenticalAttributes("SUBSITE", u_DOMNode1, u_DOMNode2, o_strOutput)) Then
  866. Exit Function
  867. End If
  868. If (Not p_IdenticalAttributes("NAVIGATIONMODEL", u_DOMNode1, u_DOMNode2, o_strOutput)) Then
  869. Exit Function
  870. End If
  871. If (u_DOMNode1.xml <> u_DOMNode2.xml) Then
  872. o_strOutput = "XML: " & u_DOMNode1.xml & " & " & u_DOMNode2.xml
  873. Exit Function
  874. End If
  875. p_IdenticalTaxonomyEntries = True
  876. End Function
  877. Private Function p_IdenticalAttributes( _
  878. ByVal i_strAttributeName As String, _
  879. ByVal u_DOMNode1 As MSXML2.IXMLDOMNode, _
  880. ByVal u_DOMNode2 As MSXML2.IXMLDOMNode, _
  881. ByRef o_strOutput As String _
  882. ) As Boolean
  883. Dim strAttribute1 As String
  884. Dim strAttribute2 As String
  885. strAttribute1 = p_ExtractAttribute(u_DOMNode1, i_strAttributeName)
  886. strAttribute2 = p_ExtractAttribute(u_DOMNode2, i_strAttributeName)
  887. If (strAttribute1 <> strAttribute2) Then
  888. o_strOutput = "Attribute " & i_strAttributeName & ": " & strAttribute1 & " & " & strAttribute2
  889. Exit Function
  890. End If
  891. p_IdenticalAttributes = True
  892. End Function