title: Parsing XSLT/Xpath data for a list of XML nodes
body: <p>I am searching for a lib or tool or even some simple code that can parse the Xpath/XSLT data in our XSLT files to produce a Dictionary/List/Tree of all the XML nodes that the XSLT is expecting to work on or find.  Sadly everything I am finding is dealing with using XSLT to parse XML rather than parsing XSLT.  And the real difficult part I'm dealing with is how flexible XPath is.</p>
  
  <p>For example in the several XSLT files we work with an entry may select on</p>
  
  <pre><code>nodeX/nodeY/nodeNeeded;
  </code></pre>
  
  <p>OR</p>
  
  <pre><code>../nodeNeeded;
  </code></pre>
  
  <p>OR</p>
  
  <p>select <code>nodeX</code> then select <code>nodeY</code> then select <code>nodeNeeded</code>;
  and so forth.</p>
  
  <p>What we would like to do is to be able to parse out that XSLT doc and get a data structure of sorts that explicitly tell us that the XSLT is looking for nodeNeeded in path nodeX, nodeY so that we can custom build the XML data in a minimalism fashion</p>
  
  <p>Thanks!</p>
  
  <p>Here is a mocked up sub-set of data for visualization purposes:</p>
  
  <pre><code>&lt;server_stats&gt;
      &lt;server name="fooServer"&gt;
          &lt;uptime&gt;24d52m&lt;/uptime&gt;
          &lt;userCount&gt;123456&lt;/userCount&gt;
          &lt;loggedInUsers&gt;
              &lt;user name="AnnaBannana"&gt;
                  &lt;created&gt;01.01.2012:00.00.00&lt;/created&gt;
                  &lt;loggedIn&gt;25&lt;/loggedIn&gt;
                  &lt;posts&gt;3&lt;/posts&gt;
               &lt;/user&gt;
           &lt;/loggedInUsers&gt;
           &lt;temperature&gt;82F&lt;/temperature&gt;
           &lt;load&gt;72&lt;/load&gt;
           &lt;mem_use&gt;45&lt;/mem_use&gt;
           &lt;visitors&gt;
               &lt;current&gt;42&lt;/current&gt;
               &lt;browsers name="mozilla" version="X.Y.Z"&gt;22&lt;/browsers&gt;
               &lt;popular_link name="index.html"&gt;39&lt;/popular_link&gt;
               &lt;history&gt;
                   &lt;max_visitors&gt;789&lt;/max_visitors&gt;
                   &lt;average_visitors&gt;42&lt;/average_visitors&gt;
               &lt;/history&gt;
           &lt;/visitors&gt;
       &lt;/server&gt;
   &lt;/server_stats&gt;
  </code></pre>
  
  <p>From this one customer may just want create an admin HTML page where they pull the hardware stats out of the tree, and perhaps run some load calculations from the visitor count.  Another customer may just want to pull just the visitor count information to display as information on their public site.  To have each of these customers system load to be as small as possible we would like to parse their stat selecting XSLT and provide them with just the data they need (which has been requested).  Obviously the issue is that one customer may perform a direct select on the visitor count node and another may select the visitors node and select each of the child nodes they want etc.</p>
  
  <p>The 2 hypothetical customers looking for the "current" node in "visitors" might have XSLT looking like:</p>
  
  <pre><code>&lt;xsl:template match="server_stats/server/visitors"&gt;
      &lt;xsl:value-of select="current"/&gt;
  &lt;/xsl:template&gt;
  
  OR
  
  &lt;xsl:template match="server_stats"&gt;
       &lt;xsl:for-each select="server"&gt;
            &lt;xsl:value-of select="visitors/current"/&gt;
            &lt;xsl:value-of select="visitors/popular_link"/&gt;
       &lt;/xsl:for-each&gt;
  &lt;/xsl:template&gt;
  </code></pre>
  
  <p>In this example both are trying to select the same node but the way they do it is different and "current" is not all that specific so we also need the path they used to get there since "current" could be nodes for several items.  This hurts us from just looking for "current" in their XSLT and because the way they access the path can be very different we cant just search for the whole path either.</p>
  
  <p>So the result we would like is to parse their XSLT and give us say a List of stats:</p>
  
  <pre><code>Customer 1:
  visitors/current
  Customer 2:
  visitors/current
  visitors/popular_link
  </code></pre>
  
  <p>etc.</p>
  
  <p>Some example selects that break the solution provided below which we will be working on solving:</p>
  
  <pre><code>&lt;xsl:variable name="fcolor" select="'Black'"/&gt; results in a /'Black' entry
  &lt;xsl:for-each select="server"&gt; we get the entry, but its children don't show it anymore
  &lt;xsl:value-of select="../../@name"/&gt;  This was kind of expected, we can try to figure out how to skip attribute based selections but the relative paths show up as I thought they would
  &lt;xsl:when test="substring(someNode,1,2)=0 and substring(someNode,4,2)=0 and substring(someNode,7,2)&gt;30"&gt;  This one is kind of throwing me, because this shows up as a path item, it's due to the when check in the solution but I don't see any nice solution since the same basic statement could have been checking for a branching path, so this might just be one of those cases we need to post-process or something of that nature.
  </code></pre>