none
XML WHERE clause on element attribute

    Soru

  • Hi everyone,

    I would appreciate your help as I am new to PS.

    What I am doing is performing a recursive iteration on a folder files and I would like to to get the corresponding <Columns> tags for which the file name is equal to the "Name" attribute in the <File> tag.

    The XML file has the following structure:

    <?xml version="1.0" encoding="utf-8"?>
    <Files>
    <File Name = "C:\Export\File1.txt">
    <Columns>
    <Column name="Description" type="Text">
    <Values>
    <Value>This is a test file</Value>
    </Values>
    </Column>
    <Column name="Author" type="Text">
    <Values>
    <Value>Test User</Value>
    </Values>
    </Column>
    <Column name="Company" type="Text">
    <Values>
    <Value>Test Company</Value>
    </Values>
    </Column>
    <Column name="Date Created" type="DateTime">
    <Values>
    <Value>1/1/2011</Value>
    </Values>
    </Column>
    <Column name="Date Modified" type="DateTime">
    <Values>
    <Value>1/1/2011</Value>
    </Values>
    </Column>
    <Column name="Date Scanned" type="DateTime">
    <Values>
    <Value>1/1/2011</Value>
    </Values>
    </Column>
    </Columns>
    </File>
    </Files>
    

    So far my code looks like this:

    Param (
               [parameter(Mandatory=$true)][string]$LocalPath, 
               [parameter(Mandatory=$false)][string]$XMLFilePath
               )
    
            $files = Get-ChildItem $LocalPath -Recurse
    		$metadataXML = [xml] (Get-Content ($XMLFilePath))
            
        $files | ForEach-Object {
    
    $metadataXML.Files.File.Name | where { $metadataXML.Files.File.Name -eq $currentfileName }  
    ......some other actions
    
    }

    However $metadataXML.Files.File.Name | where { $metadataXML.Files.File.Name -eq $currentfileName } does not perform what I need.

    Could you please advise me.

    Thanks in advance

    23 Ocak 2012 Pazartesi 12:32

Yanıtlar

  • You are still not being clear, because your code doesn't make sense:

     $files | ForEach-Object {

           #Here I need to get only the part of XML regarding the current file from $files | ForEach-Object
    $metadataXML.Files.File.Name | where { $metadataXML.Files.File.Name -eq $currentfileName

    #Here I will extract the values from the <Column> tags
    $metadataManifest.Columns.Column | ForEach-Object
    {

    }

    Please state in plain language what you are trying to achieve, because looking at this, it is not obvious.

    $currentfileName is a variable you are just picking out of nowhere, it has no value.  You are piping $files to a Foreach-Object, which means what follows will be done for every file in the array.  But within the Foreach-Object, you once again pipe a single value (name) to a non-sensical query.

     


    Grant Ward, a.k.a. Bigteddy

    What's new in Powershell 3.0 (Technet Wiki)

    Network Live Audit - Powershell script
    23 Ocak 2012 Pazartesi 14:32
  • YOu need to use XPAth to query for th ename

    I believe the XPath will look like this.

    $xml.selectSingleNode("//[@name=$currentFile]")

    The will return the parent node. The children will be the remainder of the values sought.

    YOu xml is badly broken.  XML is xcase sensitive.  You cannot have attributes with the same meaning in different cases.  Look at name.  It  is name sometimes and Name at others.  This is illegal.

     

     


    jv
    23 Ocak 2012 Pazartesi 17:08

Tüm Yanıtlar

  • Essentially what you are doing is this:

    $matchingFile = gci ([xml]$xml = gc file.xml).Files.File.Name
    
    


    Grant Ward, a.k.a. Bigteddy

    What's new in Powershell 3.0 (Technet Wiki)

    Network Live Audit - Powershell script
    23 Ocak 2012 Pazartesi 13:12
  • If your xml document contains many files that you want to look for, you can use code similar to this:

    [xml]$xml = gc file.xml
    $fileList = $xml.Files.File | select -ExpandProperty name
    $files = Get-ChildItem $fileList
    
    


    Grant Ward, a.k.a. Bigteddy

    What's new in Powershell 3.0 (Technet Wiki)

    Network Live Audit - Powershell script
    23 Ocak 2012 Pazartesi 13:56
  • Hi Grant,

    Thanks for looking into this. May be I wasn't clear enough. Based in the inserted sample xml above I need is to have something like this (see inline comments):

    Param (
               [parameter(Mandatory=$true)][string]$LocalPath, 
               [parameter(Mandatory=$false)][string]$XMLFilePath
               )
    
            $files = Get-ChildItem $LocalPath -Recurse
             $metadataXML = [xml] (Get-Content ($XMLFilePath))
            
            $files | ForEach-Object {
    
           #Here I need to get only the part of XML regarding the current file from $files | ForEach-Object
    		$metadataXML.Files.File.Name | where { $metadataXML.Files.File.Name -eq $currentfileName }  
    
    		#Here I will extract the values from the <Column> tags
    		$metadataManifest.Columns.Column | ForEach-Object 
    		{
    		 
    		}
           }
    

     

     

     

    23 Ocak 2012 Pazartesi 14:21
  • You are still not being clear, because your code doesn't make sense:

     $files | ForEach-Object {

           #Here I need to get only the part of XML regarding the current file from $files | ForEach-Object
    $metadataXML.Files.File.Name | where { $metadataXML.Files.File.Name -eq $currentfileName

    #Here I will extract the values from the <Column> tags
    $metadataManifest.Columns.Column | ForEach-Object
    {

    }

    Please state in plain language what you are trying to achieve, because looking at this, it is not obvious.

    $currentfileName is a variable you are just picking out of nowhere, it has no value.  You are piping $files to a Foreach-Object, which means what follows will be done for every file in the array.  But within the Foreach-Object, you once again pipe a single value (name) to a non-sensical query.

     


    Grant Ward, a.k.a. Bigteddy

    What's new in Powershell 3.0 (Technet Wiki)

    Network Live Audit - Powershell script
    23 Ocak 2012 Pazartesi 14:32
  • Sorry but I missed to paste the $currentfile variable. I am including it now in the script.

    Param (
           [parameter(Mandatory=$true)][string]$LocalPath, 
           [parameter(Mandatory=$false)][string]$XMLFilePath
           )
    
        $files = Get-ChildItem $LocalPath -Recurse
    	$metadataXML = [xml] (Get-Content ($XMLFilePath))
    		
    	$files | ForEach-Object {
    
    	$currentfileName = $_.FullName
    	 
    	       #Here is my problem where I need to get only the part of XML regarding the current file from $files | ForEach-Object
    	 $metadataXML.Files.File.Name | where { $metadataXML.Files.File.Name -eq $currentfileName }  
    
    	#Here I will extract the values from the <Column> tags
    	 $metadataManifest.Columns.Column | ForEach-Object 
    		{
    		 #some other code here
    		}
    	}
    

    And here is the explatation:

    I am making script which would iterate through the file system and there will be an XML file describing the files in the file system with their properties like Author, DateCreated etc..

    The XML file has the format shown above. What I would like my script to do is to: for each file in the file system to get the relevant xml part from the xml file based on the property "Name" in the tag <File> and then in this part to iterate through all the tags <Column> and get their properties.

    I hope I made myself clear this time.

    Thanks for looking into this.

    23 Ocak 2012 Pazartesi 15:02
  • YOu need to use XPAth to query for th ename

    I believe the XPath will look like this.

    $xml.selectSingleNode("//[@name=$currentFile]")

    The will return the parent node. The children will be the remainder of the values sought.

    YOu xml is badly broken.  XML is xcase sensitive.  You cannot have attributes with the same meaning in different cases.  Look at name.  It  is name sometimes and Name at others.  This is illegal.

     

     


    jv
    23 Ocak 2012 Pazartesi 17:08
  • This gets you close after you fix the XML errors.

    $xml.selectNodes('//*/File[@Name="C:\Export\File1.txt"]')|select -expand columns|select -expand column

    The schema is about as schizophrenic of a schema as I have ever seen.  It mixes very different methodolgies that make querying this XML difficult by any means.

    You need to choose with fully attribute schema structure or an unattributed structure if you want the schema to actually work.

    XML is not just thngs wrapped in tags.  It is a formal data definition system.

    For what you are trying to do you would be better off with a CSV file which is easier to manipulate if you do not know XML or data.


    jv

    • Düzenleyen jrv 23 Ocak 2012 Pazartesi 17:20
    23 Ocak 2012 Pazartesi 17:19
  • "Thanks" jrv.

    Let me just say this is sample data and is really not something you should be focused on.

    As much as I appreciate your advice on Xpath I must say I find your other comment I quote "The schema is about as schizophrenic of a schema as I have ever seen" quire rude and unadequate. As you had already commented on my post I see you went back 10 minutes later and add this absolutely inapropriate comment.

    If you are so bored with "dummy" questions you should probably consider changing your job as forum contributor no matter how good you are at coding.

     

    23 Ocak 2012 Pazartesi 17:45
  • "Thanks" jrv.

    Let me just say this is sample data and is really not something you should be focused on.

    As much as I appreciate your advice on Xpath I must say I find your other comment I quote "The schema is about as schizophrenic of a schema as I have ever seen" quire rude and unadequate. As you had already commented on my post I see you went back 10 minutes later and add this absolutely inapropriate comment.

    If you are so bored with "dummy" questions you should probably consider changing your job as forum contributor no matter how good you are at coding.

     


    In this case 'schizophrenic' means that the design of the schema is in conflict with itself.  This is one possible problem that a schma can have and is one which makes it very difficult to query.

    I posted back to advise you that the schema wuyld be very hard to manage od to th e issues it has.  If you want some pointers on how to design a schema that is easy to query and maintain I can point you to some resources.

    You need to fix the obvious errors in the 'case' of attributes but you should really consifer using a fully attributed model.

    I have no idea why you are taking technical criticism in such a person way.

     

     


    jv
    • Düzenleyen jrv 23 Ocak 2012 Pazartesi 18:31
    23 Ocak 2012 Pazartesi 18:31
  • Hi LadySQLBI,

    Were you able to find a solution for this problem?  If so, please close this thread.  If not, please update us on the status and we can assist you.

    Thanks,


    Rich Prescott | Infrastructure Architect, Windows Engineer and PowerShell blogger | MCITP, MCTS, MCP

    Engineering Efficiency
    @Rich_Prescott
    Windows System Administration tool
    AD User Creation tool

    19 Şubat 2012 Pazar 20:52
    Moderatör