3

I've got a very simple xml, as below:

<?xml version="1.0" encoding="utf-8"?>
<First>
  <Second>
    <Folder>today</Folder>
    <FileCount>10</FileCount>
  </Second>
  <Second>
    <Folder>tomorrow</Folder>
    <FileCount>90</FileCount>
  </Second>
  <Second>
    <Folder>yesterday</Folder>
    <FileCount>22</FileCount>
  </Second>
</First>

Then I have a powershell script to select "Folder" element:

[xml]$xml=Get-Content "D:\m.xml"
$xml.SelectNodes("//Folder")

It outputs:

#text                                                                                                                                                                            
-----                                                                                                                                                                            
today                                                                                                                                                                            
tomorrow                                                                                                                                                                         
yesterday 

No problem. But if I change the xml file to add "xmlns="http://schemas.microsoft.com/developer/msbuild/2003" to "First" like below:

<?xml version="1.0" encoding="utf-8"?>
<First xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Second>
    <Folder>today</Folder>
    <FileCount>10</FileCount>
  </Second>
  <Second>
    <Folder>tomorrow</Folder>
    <FileCount>90</FileCount>
  </Second>
  <Second>
    <Folder>yesterday</Folder>
    <FileCount>22</FileCount>
  </Second>
</First>

Then, my powershell script outputs nothing. Why? How to change my powershell script to support this xmlns?

Thanks a lot.

har07
  • 88,338
  • 12
  • 84
  • 137
vik santata
  • 2,989
  • 8
  • 30
  • 52

1 Answers1

4

What you added is default namespace. Unlike prefixed namespace, descendant elements inherit ancestor default namespace implicitly, unless otherwise specified (using explicit prefix or local default namespace that points to different URI).

To select element in namespace, you'll need to define prefix that point to the namespace URI and use that prefix properly in your XPath, for example :

$ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
$ns.AddNamespace("d", $xml.DocumentElement.NamespaceURI)
$xml.SelectNodes("//d:Folder", $ns)
har07
  • 88,338
  • 12
  • 84
  • 137
  • Thanks, but seesm (1) Create ns to add "d" (2) Use "d"-----is a bit redundant for me. Why I need to bother myself to Select //d:Folder while make sure $ns contains a "d"? I don't find any necessary here. Also, the name of default namespace is randomly chosen, I don't see the value of its existence. Many there're some more complex scenarios that this is needed to tell some difference? Would you kindly give an example? – vik santata Jun 24 '15 at 10:23
  • Indeed the prefix `d` is randomly chosen, what matter is the URI it points to, and that information carried by the `$ns`. That said, you need both step (1) & (2) – har07 Jun 24 '15 at 10:27
  • Just to avoid confusion, it isn't *default namespace* that is randomly chosen, it is *the prefix* to be used in XPath that is random. The prefix can be anything, roughly speaking, as long as it points to the default namespace URI – har07 Jun 24 '15 at 10:33
  • Thanks, but I could think of if I am the implementer of XML standard, I would consider default namespace as "", then using empty prefix is OK. Surely my assumption is incorrect, but why cannot be like this? I mean, is there any complex situations that we always need a randomly selected string to represent default namespace, or else we'll have logical conflicts? – vik santata Jun 24 '15 at 11:01
  • Such behavior of XML parser across languages -maybe not all, but many of them that I know- is due XPath specification -I've read this somewhere, maybe wrong; corrections are welcome-. In XPath, all elements without prefix are bound to empty namespace, while in XML, elements without namespace can be in default namespace. Anyway, I'm afraid I don't know why XPath designed that way exactly – har07 Jun 24 '15 at 13:21
  • @viksantata found formal XPath specification about "*unprefixed element name in XPath considered in namespace "null"*" : http://stackoverflow.com/a/22349809/2998271 – har07 Jun 27 '15 at 02:29
  • Since this answer solves problem in question, please consider to *accept* this as answer : http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – har07 Jun 27 '15 at 02:30