使用Powershell转换XML - 这个Sed命令的等价物是什么?

时间:2014-05-07 22:25:15

标签: powershell

我已获得以下XML代码段:

<simpleType name="StatusType">
  <restriction base="integer">
    <enumeration value="1">
      <annotation>
        <documentation>Proposed</documentation>
      </annotation>
    </enumeration>
    <enumeration value="2">
      <annotation>
        <documentation>In Use</documentation>
      </annotation>
    </enumeration>
  </restriction>
</simpleType>

我想转变成:

<simpleType name="StatusType">
  <restriction base="integer">
      <enumeration value="1" id="Proposed"/>
      <enumeration value="2" id="In Use"/>
  </restriction>
</simpleType>

我可以在Linux上使用Sed执行此操作,如下所示:

cat input_file.xml | sed -e '/<enumeration.*[^\/]>/{N;N;N;N;s/\r*\n[ \t]*//g;s/><annotation><documentation>/ id="/;s/<\/documentation><\/annotation><\/enumeration/"\//}'>output_file.xml

我希望在Windows上获得相同的结果 - 我可以尝试使用Sed的Windows端口,但我宁愿使用像Powershell这样的东西。 任何想法我如何在Powershell中实现这一目标? Get-Content有一个看起来很有用的替换函数 - 我可以做一个非常基础的替换,如下所示:

Get-Content input_file.xml | %{ $_ -replace "enumeration", "replacement_text" }

但我还不知道下一步该怎么做。

任何指针都会非常感激, 约翰

2 个答案:

答案 0 :(得分:2)

我知道你要求一个sed等价物,但是有一个用于操作XML的API,我不得不相信在XML上使用正则表达式更安全。这是实现此目的的一种方法:

$xml = [xml]@'
<simpleType name="StatusType">
  <restriction base="integer">
    <enumeration value="1">
      <annotation>
        <documentation>Proposed</documentation>
      </annotation>
    </enumeration>
    <enumeration value="2">
      <annotation>
        <documentation>In Use</documentation>
      </annotation>
    </enumeration>
  </restriction>
</simpleType>
'@

foreach ($enum in $xml.simpleType.restriction.enumeration) {
    [void]$enum.SetAttribute('id', $enum.annotation.documentation.Trim())
    [void]$enum.RemoveChild($enum.annotation)
    $enum.IsEmpty = $true
}

$xml | Format-Xml

输出:

<simpleType name="StatusType">
  <restriction base="integer">
    <enumeration value="1" id="Proposed" />
    <enumeration value="2" id="In Use" />
  </restriction>
</simpleType>

BTW Format-Xml是来自PowerShell Community Extensions模块的命令。您也可以使用Save()方法,例如:

$xml.Save("C:\foo.xml")

答案 1 :(得分:1)

我做这样的事情:

$Text = 
@'
<simpleType name="StatusType">
  <restriction base="integer">
    <enumeration value="1">
      <annotation>
        <documentation>Proposed</documentation>
      </annotation>
    </enumeration>
    <enumeration value="2">
      <annotation>
        <documentation>In Use</documentation>
      </annotation>
    </enumeration>
  </restriction>
</simpleType>
'@

$regex = 
@'
(?ms)<simpleType name="StatusType">
  <restriction base="integer">
    <enumeration value="(\d+)">
      <annotation>
        <documentation>Proposed</documentation>
      </annotation>
    </enumeration>
    <enumeration value="(\d+)">
      <annotation>
        <documentation>In Use</documentation>
      </annotation>
    </enumeration>
  </restriction>
</simpleType>
'@

if ($Text -match $regex)
{
@'
<simpleType name="StatusType">
  <restriction base="integer">
      <enumeration value="{0}" id="Proposed"/>
      <enumeration value="{1}" id="In Use"/>
  </restriction>
</simpleType>
'@ -f $Matches[1,2]
}

<simpleType name="StatusType">
  <restriction base="integer">
      <enumeration value="1" id="Proposed"/>
      <enumeration value="2" id="In Use"/>
  </restriction>
</simpleType>

它并不完全简洁,但对于下一个继承它的人来说,它是直观且易于维护的。