{"id":336,"date":"2013-08-12T12:32:02","date_gmt":"2013-08-12T10:32:02","guid":{"rendered":"http:\/\/dev.flauschig.ch\/wordpress\/?p=336"},"modified":"2013-08-12T12:32:48","modified_gmt":"2013-08-12T10:32:48","slug":"getting-xpath-from-element-xslt-and-c","status":"publish","type":"post","link":"http:\/\/dev.flauschig.ch\/wordpress\/?p=336","title":{"rendered":"Getting XPath from Element (XSLT and C#)"},"content":{"rendered":"<p>Sometimes, you want to get the XPath of an element. Here are two working solutions, one in pure XSLT and one in C#.<br \/>\nBoth of them return XPath in the form of: \/html[1]\/body[1]\/div[1]\/div[2]\/div[3]\/div[1]\/p[2]\/img[1]<\/p>\n<p><strong>C#<\/strong><\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/\/ &lt;summary&gt;\r\n\/\/\/ Gets the X-Path to a given Node\r\n\/\/\/ &lt;\/summary&gt;\r\n\/\/\/ &lt;param name=&quot;node&quot;&gt;The Node to get the X-Path from&lt;\/param&gt;\r\n\/\/\/ &lt;returns&gt;The X-Path of the Node&lt;\/returns&gt;\r\npublic string GetXPathToNode(XmlNode node)\r\n{\r\n\tif (node.NodeType == XmlNodeType.Attribute)\r\n\t{\r\n\t\t\/\/ attributes have an OwnerElement, not a ParentNode; also they have             \r\n\t\t\/\/ to be matched by name, not found by position             \r\n\t\treturn String.Format(&quot;{0}\/@{1}&quot;, GetXPathToNode(((XmlAttribute)node).OwnerElement), node.Name);\r\n\t}\r\n\tif (node.ParentNode == null)\r\n\t{\r\n\t\t\/\/ the only node with no parent is the root node, which has no path\r\n\t\treturn &quot;&quot;;\r\n\t}\r\n\r\n\t\/\/ Get the Index\r\n\tint indexInParent = 1;\r\n\tXmlNode siblingNode = node.PreviousSibling;\r\n\t\/\/ Loop thru all Siblings\r\n\twhile (siblingNode != null)\r\n\t{\r\n\t\t\/\/ Increase the Index if the Sibling has the same Name\r\n\t\tif (siblingNode.Name == node.Name)\r\n\t\t{\r\n\t\t\tindexInParent++;\r\n\t\t}\r\n\t\tsiblingNode = siblingNode.PreviousSibling;\r\n\t}\r\n\r\n\t\/\/ the path to a node is the path to its parent, plus &quot;\/node()&#x5B;n]&quot;, where n is its position among its siblings.         \r\n\treturn String.Format(&quot;{0}\/{1}&#x5B;{2}]&quot;, GetXPathToNode(node.ParentNode), node.Name, indexInParent);\r\n}\r\n<\/pre>\n<p><strong>XSLT<\/strong><\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n  &lt;xsl:template name=&quot;GeneratePath&quot;&gt;\r\n\t&lt;xsl:param name=&quot;node&quot; select=&quot;.&quot; \/&gt;\r\n\t&lt;xsl:message terminate=&quot;no&quot;&gt;\r\n\t  &lt;xsl:copy-of select=&quot;$node&quot;\/&gt;\r\n\t&lt;\/xsl:message&gt;\r\n\t&lt;xsl:apply-templates select=&quot;$node&quot; mode=&quot;StartGeneratePath&quot; \/&gt;\r\n  &lt;\/xsl:template&gt;\r\n\r\n  &lt;xsl:template match=&quot;*&quot; mode=&quot;StartGeneratePath&quot;&gt;\r\n\t&lt;xsl:call-template name=&quot;genPath&quot; \/&gt;\r\n  &lt;\/xsl:template&gt;\r\n  \r\n  &lt;xsl:template name=&quot;genPath&quot;&gt;\r\n\t&lt;xsl:param name=&quot;prevPath&quot;\/&gt;\r\n\t&lt;xsl:variable name=&quot;currPath&quot; select=&quot;concat('\/',name(),'&#x5B;',count(preceding-sibling::*&#x5B;name() = name(current())])+1,']',$prevPath)&quot;\/&gt;\r\n\t&lt;xsl:for-each select=&quot;parent::*&quot;&gt;\r\n\t  &lt;xsl:call-template name=&quot;genPath&quot;&gt;\r\n\t\t&lt;xsl:with-param name=&quot;prevPath&quot; select=&quot;$currPath&quot;\/&gt;\r\n\t  &lt;\/xsl:call-template&gt;\r\n\t&lt;\/xsl:for-each&gt;\r\n\t&lt;xsl:if test=&quot;not(parent::*)&quot;&gt;\r\n\t  &lt;xsl:value-of select=&quot;$currPath&quot;\/&gt;\r\n\t&lt;\/xsl:if&gt;\r\n  &lt;\/xsl:template&gt;\r\n<\/pre>\n<p><strong>XSLT-Usage<\/strong><\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;xsl:variable name=&quot;path&quot;&gt;\r\n  &lt;xsl:call-template name=&quot;GeneratePath&quot;&gt;\r\n\t&lt;xsl:with-param name=&quot;node&quot; select=&quot;.\/div&#x5B;@class='eintrag2']\/\/img&#x5B;1]&quot;\/&gt;\r\n  &lt;\/xsl:call-template&gt;\r\n&lt;\/xsl:variable&gt;\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes, you want to get the XPath of an element. Here are two working solutions, one in pure XSLT and one in C#. Both of them return XPath in the form of: \/html[1]\/body[1]\/div[1]\/div[2]\/div[3]\/div[1]\/p[2]\/img[1] C# \/\/\/ &lt;summary&gt; \/\/\/ Gets the X-Path to a given Node \/\/\/ &lt;\/summary&gt; \/\/\/ &lt;param name=&quot;node&quot;&gt;The Node to get the X-Path from&lt;\/param&gt; &hellip; <\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[4,3,96],"tags":[],"class_list":{"0":"entry","1":"post","2":"publish","3":"author-roemer","4":"post-336","6":"format-standard","7":"category-csharp","8":"category-programming","9":"category-xml-programming"},"acf":[],"views":6579,"_links":{"self":[{"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/336"}],"collection":[{"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=336"}],"version-history":[{"count":0,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/336\/revisions"}],"wp:attachment":[{"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=336"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=336"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=336"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}