Разобрать HTML в Чистый XML - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть файл, который заносится в файл ".EXCEL" (поддельный Excel, но это вне нашего контроля). Это на самом деле HTML, но мне трудно конвертировать его в XML.

HTML выглядит так:

<table class="c41">
    <tr class="c5">
        <td valign="top" class="c6"><p class="c7"><span class="c8">Cash Activity </span> 
        </p>
        </td>
        <td valign="top" class="c9"><p class="c10"><br/><span class="c2">FRIDAY&nbsp;&nbsp; </span><br/><span class="c2"> </span></p>
        </td>
    </tr>
    <tr class="c5">
        <td valign="top" class="c6"><p class="c11"><br/></p>
        </td>
        <td valign="top" class="c9"><p class="c10"><br/><span class="c2">05-JAN-18</span><br/><span class="c2"> </span></p>
        </td>
    </tr>
    <tr class="c12">
        <td valign="top" class="c13"><p class="c7"><span class="c14">Prior Day Available Balance</span></p>
        </td>
        <td valign="top" class="c15"><p class="c10"><span class="c16">6,472,679.45 
        </span></p>
        </td>
    </tr>
</table>

Что выглядит так:

Cash Activity               | Friday 05-JAN-18
______________________________________________
Prior Day Available Balance | $123,456.58

Есть ли в любом случае, я могу проанализировать это в Powershell для выходного XML, похожего на это:

<?xml version="1.0" encoding="utf-8" ?>
<Cash Activities>
    <Cash Activity>
        <Activity>Prior Day Available Balance</Activity>
        <Balance>123456.58</Balance>
    </Cash Activity>
</Cash Activities>

Пока что имеющийся у меня Powershell извлекает его только из электронного письма и сохраняет его в виде файла HTML:

$account = "my.email@mycompany.com"
#date to append to new file name
$date = Get-Date -Format yyyyMMdd
$searchDate = Get-Date -Format M/dd/yyyy
Write-Host $searchDate
#file to save attachment as
$newFileName = "Balance_Import_$date.xml"
$newFilePath = "C:\MyDirectory\\"

#Go into Outlook and get the MAPI
$mail = New-Object -ComObject outlook.application
$mailNS = $mail.GetNamespace("MAPI")


#get the account and Inbox we want
$myAcount = $mailNS.Folders | ? {$_.Name -eq $account}
$myInbox = $myAcount.Folders | ? {$_.Name -eq "Inbox"};
$myItems = $myAcount.Items | ? {$_.ReceivedTime.Date -eq $searchDate};

#loop through the Inbox and get any Attachments with the extension of .EXCEL
foreach ($f in $myInbox)
{
    foreach($i in $f.Items)
    {
        Write-Host "Checking "$i.Subject"..."

        if($i.ReceivedTime.Date -eq $searchDate)
        {
            Write-Host "---"
            Write-Host $i.Subject
            Write-Host "---"

            foreach($a in $i.Attachments)
            {
                if($a.FileName -like "*.EXCEL")
                {
                    #Move the attachment to the desired directory
                    $a.SaveAsFile((Join-Path $newFilePath $newFileName))
                    Write-Host $a.FileName " Saved as HTML"

                    #TODO: PARSE HTML INTO XML

                }
            }
        }

    }
} 

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

При анализе поддельного ввода в Excel / HTML могут возникнуть некоторые проблемы:

  1. HTML плохо сформирован.
  2. HTML-сущности типа &nbsp; нарушат синтаксический анализатор XML.

Предполагая, что приведенный выше пример HTML решает первую проблему, вы можете перебрать вторую проблему, расшифровав ввод следующим образом:

[xml]$html = [System.Net.WebUtility]::HtmlDecode(@'
<table class="c41">
    <tr class="c5">
        <td valign="top" class="c6"><p class="c7"><span class="c8">Cash Activity </span> 
        </p>
        </td>
        <td valign="top" class="c9"><p class="c10"><br/><span class="c2">FRIDAY&nbsp;&nbsp; </span><br/><span class="c2"> </span></p>
        </td>
    </tr>
    <tr class="c5">
        <td valign="top" class="c6"><p class="c11"><br/></p>
        </td>
        <td valign="top" class="c9"><p class="c10"><br/><span class="c2">05-JAN-18</span><br/><span class="c2"> </span></p>
        </td>
    </tr>
    <tr class="c12">
        <td valign="top" class="c13"><p class="c7"><span class="c14">Prior Day Available Balance</span></p>
        </td>
        <td valign="top" class="c15"><p class="c10"><span class="c16">6,472,679.45 
        </span></p>
        </td>
    </tr>
</table>
'@);

Теперь достаточно просто XPath выбрать узлы, которые вы хотите получить желаемый XML, который вы указали выше ( проверено и работает) :

$xml = @'
<?xml version="1.0" encoding="utf-8" ?>
<Cash Activities>

'@;
$rows = $html.DocumentElement.SelectNodes('//tr');
foreach ($row in $rows) {
    if ($row.GetAttribute('class') -eq 'c12') {
        $xml += "`t<Cash Activity>`n";
        $spans = $row.SelectNodes('.//descendant::span[@class]');
        if ($spans.Count -eq 2) {
            $xml += "`t`t<Activity>$($spans[0].InnerText.Trim())</Activity>`n"; 
            $xml += "`t`t<Balance>$($spans[1].InnerText.Trim())</Balance>`n"; 
        }
        $xml += "`t</Cash Activity>`n";
    }
}

$xml += @'
</Cash Activities>
'@;
0 голосов
/ 25 апреля 2018

Вы можете использовать COM-объект Internet Explorer, чтобы получить структуру HTML, затем извлечь нужные данные и, наконец, сгенерировать XML.Вот пример, показывающий, как вы можете это сделать:

# Create the IE com object
$oIE = New-Object -COM InternetExplorer.application

# Load the HTML document
$oie.Navigate("$pwd/html.htm")

# Function to convert the html COM object graph into PSCustomObjects
# This makes the tree a bit easier to work with since you can access by node name
function Export-Html  ($html)
{
    [pscustomobject] @{
        $html.NodeName = @{
            children = $html.Children | foreach { Export-Html $_ }
            text = $html.InnerText
        }
    }
}

# Convert the HTML into a PSCustomObject graph
$obj = Export-Html $oie.Document.Body

# Get the activity string explicitly walking the document hierarchy (could use tree search instead...)
$activity = $obj.BODY.children.
              Table.Children.
                Tbody.children.
                  TR[2].Children[0].
                   TD.
                     Text

# Get the balance, cast to double to get rid of the commas in the HTML text
[double] $balance = $obj.BODY.children.
                      Table.Children.
                        Tbody.children.
                          TR[2].Children[1].
                            TD.
                              Text

# Finally emit the XML with activity and balance substituted
@"
<?xml version="1.0" encoding="utf-8" ?>
<Cash Activities>
    <Cash Activity>
        <Activity>$activity</Activity>
        <Balance>$balance</Balance>
    </Cash Activity>
</Cash Activities>
"@
0 голосов
/ 25 апреля 2018

Поскольку существует такая вещь, как ConvertTo-XML, ваш вопрос должен звучать так: «Как преобразовать таблицу HTML в объект Powershell».

Для таблиц, где вы не знаете элементов, вы можете использовать регулярные выражения, даже если это плохая практика. https://social.technet.microsoft.com/Forums/scriptcenter/en-US/4fc6d20c-87bd-44e4-8e46-c72d63fe7b41/html-table-to-powershell-object?forum=ITCG

Как только вы поместите ваши данные в объект Powershell, вам будет очень легко менять заголовки или очищать данные так, как вам хочется.

Затем используйте вышеупомянутый командлет для преобразования в XML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...