code_junkie

Program to analyze a lot of XMLs

Nov 11th, 2011
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.61 KB | None | 0 0
  1. root 100%
  2. a*1 90%
  3. b*1 80%
  4. c*5 40%
  5.  
  6. c*4.3 4 6 40%
  7.  
  8. <xsl:for-each-group select="$docs//*" group-by="name()">
  9. <xsl:sort select="current-group-key()" />
  10. <xsl:variable name="name" as="xs:string" select="current-grouping-key()" />
  11. <xsl:value-of select="$name" />
  12. ...
  13. </xsl:for-each-group>
  14.  
  15. <xsl:variable name="docs-with" as="document-node()+"
  16. select="$docs[//*[name() = $name]" />
  17.  
  18. <xsl:variable name="elem-counts" as="xs:integer+"
  19. select="$docs-with/count(//*[name() = $name])" />
  20.  
  21. <xsl:for-each-group select="$docs//*" group-by="name()">
  22. <xsl:sort select="current-group-key()" />
  23. <xsl:variable name="name" as="xs:string" select="current-grouping-key()" />
  24. <xsl:variable name="docs-with" as="document-node()+"
  25. select="$docs[//*[name() = $name]" />
  26. <xsl:variable name="elem-counts" as="xs:integer+"
  27. select="$docs-with/count(//*[name() = $name])" />
  28. <xsl:value-of select="$name" />
  29. <xsl:text>* </xsl:text>
  30. <xsl:value-of select="format-number(avg($elem-counts), '#,##0.0')" />
  31. <xsl:text> </xsl:text>
  32. <xsl:value-of select="format-number(min($elem-counts), '#,##0')" />
  33. <xsl:text> </xsl:text>
  34. <xsl:value-of select="format-number(max($elem-counts), '#,##0')" />
  35. <xsl:text> </xsl:text>
  36. <xsl:value-of select="format-number((count($docs-with) div count($docs)) * 100, '#0')" />
  37. <xsl:text>%</xsl:text>
  38. <xsl:text>&#xA;</xsl:text>
  39. </xsl:for-each-group>
  40.  
  41. <xsl:stylesheet version="2.0"
  42. xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  43. xmlns:xs="http://www.w3.org/2001/XMLSchema"
  44. exclude-result-prefixes="xs">
  45.  
  46. <xsl:param name="dir" as="xs:string"
  47. select="'file:///path/to/default/directory?select=*.xml'" />
  48.  
  49. <xsl:output method="text" />
  50.  
  51. <xsl:variable name="docs" as="document-node()*"
  52. select="collection($dir)" />
  53.  
  54. <xsl:template name="main">
  55. <xsl:for-each-group select="$docs//*" group-by="name()">
  56. <xsl:sort select="current-group-key()" />
  57. <xsl:variable name="name" as="xs:string" select="current-grouping-key()" />
  58. <xsl:variable name="docs-with" as="document-node()+"
  59. select="$docs[//*[name() = $name]" />
  60. <xsl:variable name="elem-counts" as="xs:integer+"
  61. select="$docs-with/count(//*[name() = $name])" />
  62. <xsl:value-of select="$name" />
  63. <xsl:text>* </xsl:text>
  64. <xsl:value-of select="format-number(avg($elem-counts), '#,##0.0')" />
  65. <xsl:text> </xsl:text>
  66. <xsl:value-of select="format-number(min($elem-counts), '#,##0')" />
  67. <xsl:text> </xsl:text>
  68. <xsl:value-of select="format-number(max($elem-counts), '#,##0')" />
  69. <xsl:text> </xsl:text>
  70. <xsl:value-of select="format-number((count($docs-with) div count($docs)) * 100, '#0')" />
  71. <xsl:text>%</xsl:text>
  72. <xsl:text>&#xA;</xsl:text>
  73. </xsl:for-each-group>
  74. </xsl:template>
  75.  
  76. </xsl:stylesheet>
  77.  
  78. main
  79.  
  80. Analyzing plant_catalog.xml:
  81. Analyzing note.xml:
  82. Analyzing portfolio.xml:
  83. Analyzing note_ex_dtd.xml:
  84. Analyzing home.xml:
  85. Analyzing simple.xml:
  86. Analyzing cd_catalog.xml:
  87. Analyzing portfolio_xsl.xml:
  88. Analyzing note_in_dtd.xml:
  89. Statistical Elements Analysis of 9 xml documents with 34 elements
  90. CATALOG*2 22%
  91. CD*26 50%
  92. ARTIST*26 100%
  93. COMPANY*26 100%
  94. COUNTRY*26 100%
  95. PRICE*26 100%
  96. TITLE*26 100%
  97. YEAR*26 100%
  98. PLANT*36 50%
  99. AVAILABILITY*36 100%
  100. BOTANICAL*36 100%
  101. COMMON*36 100%
  102. LIGHT*36 100%
  103. PRICE*36 100%
  104. ZONE*36 100%
  105. breakfast-menu*1 11%
  106. food*5 100%
  107. calories*5 100%
  108. description*5 100%
  109. name*5 100%
  110. price*5 100%
  111. note*3 33%
  112. body*1 100%
  113. from*1 100%
  114. heading*1 100%
  115. to*1 100%
  116. page*1 11%
  117. para*1 100%
  118. title*1 100%
  119. portfolio*2 22%
  120. stock*2 100%
  121. name*2 100%
  122. price*2 100%
  123. symbol*2 100%
  124.  
  125. require "rexml/document"
  126. require "net/http"
  127. require "iconv"
  128. include REXML
  129. class NodeAnalyzer
  130. @@fullPathToFilesToSubNodesNamesToCardinalities = Hash.new()
  131. @@fullPathsToFiles = Hash.new() #list of files in which a fullPath node is detected
  132. @@fullPaths = Array.new # all fullpaths sorted alphabetically
  133. attr_reader :name, :father, :subNodesAnalyzers, :indent, :file, :subNodesNamesToCardinalities
  134. def initialize(aName="", aFather=nil, aFile="")
  135. @name = aName; @father = aFather; @subNodesAnalyzers = []; @file = aFile
  136. @subNodesNamesToCardinalities = Hash.new(0)
  137. if aFather && !aFather.name.empty? then @indent = " " else @indent = "" end
  138. if aFather
  139. @indent = @father.indent + self.indent
  140. @father.subNodesAnalyzers << self
  141. @father.updateSubNodesNamesToCardinalities(@name)
  142. end
  143. end
  144. @@nodesRootAnalyzer = NodeAnalyzer.new
  145. def NodeAnalyzer.nodesRootAnalyzer
  146. return @@nodesRootAnalyzer
  147. end
  148. def updateSubNodesNamesToCardinalities(aSubNodeName)
  149. aSubNodeCardinality = @subNodesNamesToCardinalities[aSubNodeName]
  150. @subNodesNamesToCardinalities[aSubNodeName] = aSubNodeCardinality + 1
  151. end
  152. def NodeAnalyzer.recordNode(aNodeAnalyzer)
  153. if aNodeAnalyzer.fullNodePath.empty? == false
  154. if @@fullPaths.include?(aNodeAnalyzer.fullNodePath) == false then @@fullPaths << aNodeAnalyzer.fullNodePath end
  155. # record a full path in regard to its xml file (records it only one for a given xlm file)
  156. someFiles = @@fullPathsToFiles[aNodeAnalyzer.fullNodePath]
  157. if someFiles == nil
  158. someFiles = Array.new(); @@fullPathsToFiles[aNodeAnalyzer.fullNodePath] = someFiles;
  159. end
  160. if !someFiles.include?(aNodeAnalyzer.file) then someFiles << aNodeAnalyzer.file end
  161. end
  162. #record cardinalties of sub nodes for a given xml file
  163. someFilesToSubNodesNamesToCardinalities = @@fullPathToFilesToSubNodesNamesToCardinalities[aNodeAnalyzer.fullNodePath]
  164. if someFilesToSubNodesNamesToCardinalities == nil
  165. someFilesToSubNodesNamesToCardinalities = Hash.new(); @@fullPathToFilesToSubNodesNamesToCardinalities[aNodeAnalyzer.fullNodePath] = someFilesToSubNodesNamesToCardinalities ;
  166. end
  167. someSubNodesNamesToCardinalities = someFilesToSubNodesNamesToCardinalities[aNodeAnalyzer.file]
  168. if someSubNodesNamesToCardinalities == nil
  169. someSubNodesNamesToCardinalities = Hash.new(0); someFilesToSubNodesNamesToCardinalities[aNodeAnalyzer.file] = someSubNodesNamesToCardinalities
  170. someSubNodesNamesToCardinalities.update(aNodeAnalyzer.subNodesNamesToCardinalities)
  171. else
  172. aNodeAnalyzer.subNodesNamesToCardinalities.each() do |aSubNodeName, aCardinality|
  173. someSubNodesNamesToCardinalities[aSubNodeName] = someSubNodesNamesToCardinalities[aSubNodeName] + aCardinality
  174. end
  175. end
  176. #puts "someSubNodesNamesToCardinalities for #{aNodeAnalyzer.fullNodePath}: #{someSubNodesNamesToCardinalities}"
  177. end
  178. def file
  179. #if @file.empty? then @father.file else return @file end
  180. if @file.empty? then if @father != nil then return @father.file else return '' end else return @file end
  181. end
  182. def fullNodePath
  183. if @father == nil then return '' elsif @father.name.empty? then return @name else return @father.fullNodePath+"/"+@name end
  184. end
  185. def to_s
  186. s = ""
  187. if @name.empty? == false
  188. s = "#{@indent}#{self.fullNodePath} [#{self.file}]n"
  189. end
  190. @subNodesAnalyzers.each() do |aSubNodeAnalyzer|
  191. s = s + aSubNodeAnalyzer.to_s
  192. end
  193. return s
  194. end
  195. def NodeAnalyzer.displayStats(aFullPath="")
  196. s = "";
  197. if aFullPath.empty? then s = "Statistical Elements Analysis of #{@@nodesRootAnalyzer.subNodesAnalyzers.length} xml documents with #{@@fullPaths.length} elementsn" end
  198. someFullPaths = @@fullPaths.sort
  199. someFullPaths.each do |aFullPath|
  200. s = s + getIndentedNameFromFullPath(aFullPath) + "*"
  201. nbFilesWithThatFullPath = getNbFilesWithThatFullPath(aFullPath);
  202. aParentFullPath = getParentFullPath(aFullPath)
  203. nbFilesWithParentFullPath = getNbFilesWithThatFullPath(aParentFullPath);
  204. aNameFromFullPath = getNameFromFullPath(aFullPath)
  205. someFilesToSubNodesNamesToCardinalities = @@fullPathToFilesToSubNodesNamesToCardinalities[aParentFullPath]
  206. someCardinalities = Array.new()
  207. someFilesToSubNodesNamesToCardinalities.each() do |aFile, someSubNodesNamesToCardinalities|
  208. aCardinality = someSubNodesNamesToCardinalities[aNameFromFullPath]
  209. if aCardinality > 0 && someCardinalities.include?(aCardinality) == false then someCardinalities << aCardinality end
  210. end
  211. if someCardinalities.length == 1
  212. s = s + someCardinalities.to_s + " "
  213. else
  214. anAvg = someCardinalities.inject(0) {|sum,value| Float(sum) + Float(value) } / Float(someCardinalities.length)
  215. s = s + sprintf('%.1f', anAvg) + " " + someCardinalities.min.to_s + "..." + someCardinalities.max.to_s + " "
  216. end
  217. s = s + sprintf('%d', Float(nbFilesWithThatFullPath) / Float(nbFilesWithParentFullPath) * 100) + '%'
  218. s = s + "n"
  219. end
  220. return s
  221. end
  222. def NodeAnalyzer.getNameFromFullPath(aFullPath)
  223. if aFullPath.include?("/") == false then return aFullPath end
  224. aNameFromFullPath = aFullPath.dup
  225. aNameFromFullPath[/^(?:[^/]+/)+/] = ""
  226. return aNameFromFullPath
  227. end
  228. def NodeAnalyzer.getIndentedNameFromFullPath(aFullPath)
  229. if aFullPath.include?("/") == false then return aFullPath end
  230. anIndentedNameFromFullPath = aFullPath.dup
  231. anIndentedNameFromFullPath = anIndentedNameFromFullPath.gsub(/[^/]+//, " ")
  232. return anIndentedNameFromFullPath
  233. end
  234. def NodeAnalyzer.getParentFullPath(aFullPath)
  235. if aFullPath.include?("/") == false then return "" end
  236. aParentFullPath = aFullPath.dup
  237. aParentFullPath[//[^/]+$/] = ""
  238. return aParentFullPath
  239. end
  240. def NodeAnalyzer.getNbFilesWithThatFullPath(aFullPath)
  241. if aFullPath.empty?
  242. return @@nodesRootAnalyzer.subNodesAnalyzers.length
  243. else
  244. return @@fullPathsToFiles[aFullPath].length;
  245. end
  246. end
  247. end
  248. class REXML::Document
  249. def analyze(node, aFatherNodeAnalyzer, aFile="")
  250. anNodeAnalyzer = NodeAnalyzer.new(node.name, aFatherNodeAnalyzer, aFile)
  251. node.elements.each() do |aSubNode| analyze(aSubNode, anNodeAnalyzer) end
  252. NodeAnalyzer.recordNode(anNodeAnalyzer)
  253. end
  254. end
  255.  
  256. begin
  257. anXmlFilesDirectory = "xmlfiles.com/examples/"
  258. anXmlFilesRegExp = Regexp.new("http://" + anXmlFilesDirectory + "([^"]*)")
  259. a = Net::HTTP.get(URI("http://www.google.fr/search?q=site:"+anXmlFilesDirectory+"+filetype:xml&num=100&as_qdr=all&filter=0"))
  260. someXmlFiles = a.scan(anXmlFilesRegExp)
  261. someXmlFiles.each() do |anXmlFile|
  262. anXmlFileContent = Net::HTTP.get(URI("http://" + anXmlFilesDirectory + anXmlFile.to_s))
  263. anUTF8XmlFileContent = Iconv.conv("ISO-8859-1//ignore", 'UTF-8', anXmlFileContent).gsub(/s+encodings*=s*"[^"]+"s*?/,"?")
  264. anXmlDocument = Document.new(anUTF8XmlFileContent)
  265. puts "Analyzing #{anXmlFile}: #{NodeAnalyzer.nodesRootAnalyzer.name}"
  266. anXmlDocument.analyze(anXmlDocument.root,NodeAnalyzer.nodesRootAnalyzer, anXmlFile.to_s)
  267. end
  268. NodeAnalyzer.recordNode(NodeAnalyzer.nodesRootAnalyzer)
  269. puts NodeAnalyzer.displayStats
  270. end
Add Comment
Please, Sign In to add comment