{"id":70,"date":"2012-08-05T19:41:22","date_gmt":"2012-08-05T18:41:22","guid":{"rendered":"http:\/\/blog.powered-up-games.com\/wordpress\/?p=70"},"modified":"2015-06-29T00:31:30","modified_gmt":"2015-06-28T23:31:30","slug":"xpath-and-the-default-namespace","status":"publish","type":"post","link":"https:\/\/powered-up-games.com\/blog\/wordpress\/archives\/70","title":{"rendered":"XPath and the default namespace"},"content":{"rendered":"<p>I&#8217;ve been working on a <a href=\"http:\/\/www.gnu.org\/software\/make\/manual\/html_node\/Overview.html#Overview\" title=\"GNU Make introduction\">make<\/a> script that extracts the files it needs to build from a Microsoft Visual Studio project file. The .vcxproj file format is <a href=\"http:\/\/www.w3.org\/TR\/xml\/\" title=\"Extensible Markup Language\">XML<\/a> so I imagined it would be easy to use a command line XML processor to do the job. However because the project file declares a default namespace this was not as easy as it first looked.<\/p>\n<p><!--more--><\/p>\n<p>One tool that can perform <a href=\"http:\/\/www.w3.org\/TR\/xpath\/\" title=\"XML Path Language\">XPath<\/a> queries on XML files is <a href=\"http:\/\/xmlsoft.org\/xmllint.html\" title=\"A command line XML tool\">xmllint<\/a>. This is part of the <a href=\"http:\/\/www.xmlsoft.org\/\" title=\"The XML C parser and toolkit of Gnome\">libxml<\/a> package and is available in most Linux distributions and also on <a href=\"http:\/\/www.cygwin.com\/\" title=\"A Linux like environment on Windows\">Cygwin<\/a>. As this script was for use with Window 7, it seemed like a good choice. The method for running an XPath query using xmllint is the undocumented command line option &#8211;xpath:<\/p>\n<pre><code>$ xmllint --xpath \/XmlTag1\/XmlTag2\/etc... XmlFile.xml<\/code><\/pre>\n<p>This works fine on simple sample XML files such as the standard <a href=\"http:\/\/www.w3schools.com\/dom\/books.xml\" title=\"A simple sample XML file\">books.xml<\/a>. However, running this against a .vcxproj file produces:<\/p>\n<pre><code>$ xmllint --xpath \"\/Project\/ItemGroup\/ClCompile\" project.vcxproj\r\nXPath set is empty<\/code><\/pre>\n<p>And if that fails, then the actual query that I want to run causes an error:<\/p>\n<pre><code>$ xmllint --xpath \"\/Project\/ItemGroup\/ClCompile\/@Include\" project.vcxproj\r\nSegmentation fault (core dumped)<\/code><\/pre>\n<p>The reason this doesn&#8217;t work is down to the project file&#8217;s use of the default namespace. The .vcxproj file defines its default namespace as:<\/p>\n<pre><code>http:\/\/schemas.microsoft.com\/developer\/msbuild\/2003<\/code><\/pre>\n<p>This means that all of the XML tags in the .vcxproj file belong to this namespace. But there is no way in an XPath query to specify what the default namespace is. You need to have mapped the namespace to an identifier within the tool first.<\/p>\n<p>xmllint can do this remapping in its shell mode. But there is no current method to specify the default namespace through a command line option. This means the above XPath query would need to be as follows:<\/p>\n<pre><code>$ xmllint --xpath \"\/*[namespace-uri()='http:\/\/schemas.microsoft.com\/developer\/msbuild\/2003' and local-name()='Project']\/*[namespace-uri()='http:\/\/schemas.microsoft.com\/developer\/msbuild\/2003' and local-name()='ItemGroup']\/*[namespace-uri()='http:\/\/schemas.microsoft.com\/developer\/msbuild\/2003' and local-name()='ClCompile']\" project.vcxproj<\/code><\/pre>\n<p>Within the make script itself, I can use variables or macro expansion to make the command a bit more manageable. A more hackier alternative would be to strip out the default namespace declaration from the .vcxproj file. This can be done with the <a href=\"http:\/\/www.gnu.org\/software\/sed\/manual\/html_node\/Introduction.html#Introduction\" title=\"sed is a stream editor\">sed<\/a> program:<\/p>\n<pre><code>$ sed -e \"s\/xmlns\/ignore\/\" project.vcxproj | xmllint --xpath \"\/Project\/ItemGroup\/ClCompile\/@Include\" -<\/code><\/pre>\n<p>Another shorter hack would be to relax the matching criteria: <\/p>\n<pre><code>$ xmllint --xpath \"\/\/*[local-name()='ClCompile']\/@Include\" project.vcxproj<\/code><\/pre>\n<p>But however I implement it, the results need further parsing as they come back in the form of key=&#8221;value&#8221; attributes:<\/p>\n<pre><code> Include=\"file1.cpp\" Include=\"file2.cpp\"<\/code><\/pre>\n<p>I can use another sed expression to turn that into a simple white-space separated list. But I&#8217;ll leave that for another post.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been working on a make script that extracts the files it needs to build from a Microsoft Visual Studio project file. The .vcxproj file format is XML so I imagined it would be easy to use a command line XML processor to do the job. However because the project file declares a default namespace [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[16,17,14,15,12,13,11,18],"class_list":["post-70","post","type-post","status-publish","format-standard","hentry","category-programming","tag-cygwin","tag-default-namespace","tag-libxml","tag-linux","tag-xml","tag-xmllint","tag-xpath","tag-xpath-set-is-empty"],"_links":{"self":[{"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/posts\/70","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/comments?post=70"}],"version-history":[{"count":23,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/posts\/70\/revisions"}],"predecessor-version":[{"id":298,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/posts\/70\/revisions\/298"}],"wp:attachment":[{"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/media?parent=70"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/categories?post=70"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/powered-up-games.com\/blog\/wordpress\/wp-json\/wp\/v2\/tags?post=70"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}