none
Хранение типизированных данных в XML RRS feed

  • Вопрос

  • Добрый день!

    В данный момент пытаюсь реализовать ini-файл для PS-скрипта на основе XML.

    Загвоздка в следующем.

    В моем скрипте используется командлет Get-ADUser, у которого есть параметр -ResultSetSize. Согласно описанию, тип этого параметра <System.Nullable[System.Int32]>. То есть этот параметр может быть как целым чилом, так и $null.

    В самом PS скрипте оба случая работают отлично. Но у меня есть потребность вынести все переменные в ini-файл.

    Если я пишу в XML:

    <Settings>

       <ResultSetSize>10</ResultSetSize>

    </Settings>

    и затем получаю тип переменной в скрипте:

    $XMLinstance = [xml](gc "blablabla.xml")

    $XMLinstance.Settings.ResultSetSize.GetType().Name
    String

    Как видно из вывода, мы получили строку, а не число. Конечно я всегда могу сделать явное преобразование типов:

    ([int]($XMLinstance.Settings.ResultSetSize)).GetType().Name
    Int32

    и получить число. Все что мне пришло в голову - это проверять строку на пустоту:

    if ($XMLinstance.Settings.ResultSetSize -eq "")

       {$a = $null}

    else

       {$a = [int]($XMLinstance.Settings.ResultSetSize)}

    Но согласитесь, это выглядит как-то убого.

    Отсюда вопрос, могу ли я получать из XML-файла что-то отличное от строковых данных?

Ответы

  • Можно хранить в XML любые данные которые вы можете представить как текст (для сохранения), а затем восстановить из текста (при загрузке).

    Чтобы быть уверенным в типе данных который хранится в параметре, можно сохранять описание этого типа в том-же XML. Например такой подход используют командлеты Import/Export-CliXML для сохранения объектов в текстовое представление и восстановление их. Это только один из вариантов работы с XML и работает он только для конкретной задачи. Ниже пример как можно использовать его для сохранения и загрузки настроек.

    PS C:\Temp> $settings = New-Object psobject @{ParamInt = 1; ParamStr = "Test"}
    PS C:\Temp> $settings | Export-Clixml config.xml
    PS C:\Temp> $settings2 = Import-Clixml .\config.xml
    PS C:\Temp> $settings2.ParamInt
    1
    PS C:\Temp> $settings2.ParamInt.gettype().fullname
    System.Int32
    PS C:\Temp> $settings2.ParamStr
    Test
    PS C:\Temp> $settings2.ParamStr.gettype().fullname
    System.String

    Разумеется если вы хотите работать с XML напрямую, Import/Export-CliXML вам не подойдёт - он работает со своим подформатом XML.

    Чтобы преобразовывать строку в число без опасений получить ошибку и не "убого", можно воспользоваться специально предназначенным для этого, статическим методом TryParse:

    PS C:\Temp> $String = "123"
    PS C:\Temp> $Number = -1
    PS C:\Temp> if ([int]::TryParse($String, [ref]$Number)) {"String parsed to int"} else {"String not a correct int"}
    String parsed to int
    PS C:\Temp> $Number
    123


    AKA Xaegr, MVP: PowerShell Блог: http://xaegr.wordpress.com

    • Помечено в качестве ответа Dmitry Zobnin 28 мая 2012 г. 9:16
    Модератор

Все ответы

  • xml нужно читать не через Get-Content, а через Import-Clixml:

    $XMLinstance = Import-Clixml blablabla.xml


  • Можно хранить в XML любые данные которые вы можете представить как текст (для сохранения), а затем восстановить из текста (при загрузке).

    Чтобы быть уверенным в типе данных который хранится в параметре, можно сохранять описание этого типа в том-же XML. Например такой подход используют командлеты Import/Export-CliXML для сохранения объектов в текстовое представление и восстановление их. Это только один из вариантов работы с XML и работает он только для конкретной задачи. Ниже пример как можно использовать его для сохранения и загрузки настроек.

    PS C:\Temp> $settings = New-Object psobject @{ParamInt = 1; ParamStr = "Test"}
    PS C:\Temp> $settings | Export-Clixml config.xml
    PS C:\Temp> $settings2 = Import-Clixml .\config.xml
    PS C:\Temp> $settings2.ParamInt
    1
    PS C:\Temp> $settings2.ParamInt.gettype().fullname
    System.Int32
    PS C:\Temp> $settings2.ParamStr
    Test
    PS C:\Temp> $settings2.ParamStr.gettype().fullname
    System.String

    Разумеется если вы хотите работать с XML напрямую, Import/Export-CliXML вам не подойдёт - он работает со своим подформатом XML.

    Чтобы преобразовывать строку в число без опасений получить ошибку и не "убого", можно воспользоваться специально предназначенным для этого, статическим методом TryParse:

    PS C:\Temp> $String = "123"
    PS C:\Temp> $Number = -1
    PS C:\Temp> if ([int]::TryParse($String, [ref]$Number)) {"String parsed to int"} else {"String not a correct int"}
    String parsed to int
    PS C:\Temp> $Number
    123


    AKA Xaegr, MVP: PowerShell Блог: http://xaegr.wordpress.com

    • Помечено в качестве ответа Dmitry Zobnin 28 мая 2012 г. 9:16
    Модератор
  • Спасибо за помощь, в данном конкретном случае Clixml я использовать, похоже, не могу, т.к. XML формируется руками, но командлет мне наверняка пригодится в будущем.

    У себя оставил вариант:

    if ([int]::TryParse($XMLinstance.Settings.ResultSetSize, [ref]$ResultSetSize))
          {write-host "Параметр ResultSetSize был преобразован в целое число"}
     else
          {
            write-host "Параметр ResultSetSize не является целым числом, принимаем его за null"
            $ResultSetSize = $null
          }