0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

XMLアクティビティを使ってプロセスの情報を抽出しよう Part2

Posted at

はじめに

前回は、XMLの概念及びUiPath StudioにおけるXMLの操作方法についてご紹介しました。実際に、RPA開発者が日々触っているワークフロー(xmalファイルとして保存)もXML言語で記述されています。XML言語を使いこなせば、ワークフローを開かなくても、プロセスの編集と情報抽出が可能になります。特に、たくさんのプロセスに対して、一括で情報抽出の際に、この方法は非常に効率的なので、本記事は、Part 1の内容を土台にしてXMLによるxamlファイル情報抽出の方法について紹介しようと思います。まだPart1がご覧になっていない方はぜひ目を通していただければ幸いです。

環境準備

項目 バージョン
UiPath Studio 2024.10.6
UiPath.WebAPI.Activities 1.21.1
対応OS Windows

XMLで記述されるxamlの構造

簡単なワークフローを作成してxmalファイルの実態を確認してみましょう。以下の手順に従って作成します。

①xmlReaderという名前を付けてプロジェクトを作成します。
②sampleという名前を付けて新しいシーケンスを作成します。
③メッセージボックスを配置して、"Hello World!"のテキストを記述します。
④シーケンスを保存して、プロジェクトフォルダでsample.xmalをNotepad++で開きます。

すると、以下のXML文章が表示されます。長いため、同じタグの一部のChild Elementを削除しました。

sample.xamlのXML表示
<Activity mc:Ignorable="sap sap2010" x:Class="sample"
 VisualBasic.Settings="{x:Null}"
 sap2010:WorkflowViewState.IdRef="sample_1"
 xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation"
 xmlns:sap2010="http://schemas.microsoft.com/netfx/2010/xaml/activities/presentation"
 xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System.Private.CoreLib"
 xmlns:sco="clr-namespace:System.Collections.ObjectModel;assembly=System.Private.CoreLib"
 xmlns:ui="http://schemas.uipath.com/workflow/activities" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <TextExpression.NamespacesForImplementation>
    <sco:Collection x:TypeArguments="x:String">
      <x:String>System.Activities</x:String>
      <x:String>System.Activities.Statements</x:String>
      <!-- 長いので省略 -->
    </sco:Collection>
  </TextExpression.NamespacesForImplementation>
  <TextExpression.ReferencesForImplementation>
    <sco:Collection x:TypeArguments="AssemblyReference">
      <AssemblyReference>Microsoft.VisualBasic</AssemblyReference>
      <AssemblyReference>mscorlib</AssemblyReference>
      <!-- 長いので省略 -->
    </sco:Collection>
  </TextExpression.ReferencesForImplementation>
  <Sequence DisplayName="sample" sap:VirtualizedContainerService.HintSize="1120,786.04" sap2010:WorkflowViewState.IdRef="Sequence_1">
    <sap:WorkflowViewStateService.ViewState>
      <scg:Dictionary x:TypeArguments="x:String, x:Object">
        <x:Boolean x:Key="IsExpanded">True</x:Boolean>
      </scg:Dictionary>
    </sap:WorkflowViewStateService.ViewState>
    <ui:MessageBox Caption="{x:Null}" ChosenButton="{x:Null}" AutoCloseAfter="00:00:00" 
	 DisplayName="メッセージ ボックス" sap:VirtualizedContainerService.HintSize="416,108"
	 sap2010:WorkflowViewState.IdRef="MessageBox_2" Text="[&quot;Hello World&quot;]" />
  </Sequence>
</Activity>

読みにくいですね。もっと中身を簡略化して構造だけを残すと、このようになります。前回の復習ですね。

sample.xamlの構造(簡略版)
<Activity(ルート要素) x:Class="sample"(属性)
 xmlns:ui="http://schemas.uipath.com/workflow/activities"(名前空間)>
  <TextExpression.NamespacesForImplementation(子要素)>
    <sco:Collection(孫要素) x:TypeArguments="x:String"(孫要素の属性)>
      <x:String(曾孫要素)>System.Activities(曾孫要素のテキスト)</x:String>
    </sco:Collection>
  </TextExpression.NamespacesForImplementation>
  <Sequence(子要素) DisplayName="sample"(子要素の属性)>
    <ui:MessageBox(孫要素) Caption="{x:Null}" ChosenButton="{x:Null}" AutoCloseAfter="00:00:00" 
	 DisplayName="メッセージ ボックス" sap:VirtualizedContainerService.HintSize="416,108"
	 sap2010:WorkflowViewState.IdRef="MessageBox_2" Text="[&quot;Hello World&quot;]"(孫要素の属性)/>
  </Sequence>
</Activity>

たくさんの情報が入っていますが、今回の抽出作業に関する項目だけ、ご理解いただければと思います。

<Activity>タグ:UiPathワークフローのルート要素であり、ワークフロー全体を囲んでいます。属性には、ワークフローの名前空間や、Visual Basic設定、ワークフローのIDなどが含まれます。

xmlns:ui="http://schemas.uipath.com/workflow/activities":UiPathのワークフローアクティビティを識別する名前空間です。ui プレフィックスを使って、UiPathのUI操作に関連するアクティビティ(例:メッセージボックス、ダイアログ、フォーム、UI操作など)を参照します。

<TextExpression.NamespacesForImplementation>タグ:ワークフロー内で使用する名前空間のリストを定義します。ここには、System.ActivitiesやUiPathのアクティビティや基本的な.NET名前空間が多数含まれています。

<Sequence>タグ:UiPathのシーケンスアクティビティを表します。シーケンスアクティビティは、順番に実行されるアクティビティの集合です。DisplayName="sample"で、シーケンスの名前が指定されています。

<ui:MessageBox>タグ:UiPathの「メッセージボックス」アクティビティを定義します。中のText="[&quot;Hello World&quot;]" は、メッセージボックスに表示するテキスト"Hello World"を指定しています。

ワークフローの実装

今回の目標は、UiPathフォルダ(C:\Users\UserID\Documents\UiPath)配下における、すべてのプロセスの中のOpenBrowserで記録されているウェブサイトのURLを抽出しようと思います。以下はイメージです。

image.png

ワークフローが少し長いため、まず完成図を頭に入れて、ステップバイステップで作成していきましょう。

無題.jpg

では、始めましょう。

①プロセスとそのURLを記録するために、「データテーブルを構築」を使います。ProcessNameとURLという2つの列を構築してdtUrlInfoとして保存します。

image.png

②UiPathフォルダ配下のプロジェクトフォルダの情報を取得します。

image.png

上図の赤枠の情報を取得するために、System.IO.DirectoryクラスのGetDirectoriesメソッドを利用します。

コード
Dim fileDirectories() As String
fileDirectories = System.io.Directory.GetDirectories("C:\Users\UserID\Documents\UiPath")

次に、各フォルダ内のxmalファイルを探しだすために、「繰り返し(コレクションの各要素)」を使います。

コード
For Each dire In fileDirectories
  Body   
Next

完成図は以下の通りです。

image.png

③Bodyを展開します。

まず、各プロセスの名前を取得します。Studioでプロセスを作成したら、UiPath配下でプロジェクトフォルダが作成され、そのプロジェクトフォルダの名前はプロセスの名前になります。

コード
Dim fileName As String
fileName = System.IO.Path.GetFileName(dire)

image.png

次に、取得したプロジェクトフォルダの配下のxmalファイルを探し出します。一つのプロジェクトフォルダには複数のxmalが存在可能なので、配列の変数xamlFilesを作成して情報を保存します。

コード
Dim xamlFiles() As String
xmlFiles = System.IO.Directory.GetFiles(dire,"*.xaml")

image.png

さらに、xmalファイルをループし、URLの取得を準備します。

コード
For Each xamlFile in xamlFiles 
 Body
Next

image.png

④Body2を展開します。いよいよXML操作が始まりますね!

i.「テキストファイルを読み込み」でxamlFileをstXamlとして出力します。

image.png

ii.「XMLを逆シリアル化」でstXamlをXDocumentに変換します。

image.png

iii.名前空間の取得

名前空間は、XML文書内で同じ要素(もしくは、同じ種類の要素)や属性が重複しないように区別するための仕組みです。XMLでは、同じ要素(もしくは、同じ種類の要素)が異なる名前空間に属していることがよくあります。そのため、名前空間を管理することが非常に重要です。通常、名前空間はxmlns属性を使って定義され、XMLタグで指定されたプレフィックス(例えばuisap)が、実際にどの名前空間に属するかを示します。イメージとして、名前空間は要素の住所のように、その要素の取得の前提となります。

さきほど説明した通り、uiというプレフィックスは、UiPathのアクティビティに関連する名前空間を指します。「OpenBrowser」もこの名前空間を利用しているため、XMLで「OpenBrowser」の情報を抽出するために、uiプレフィックスの指定が前提となります。

Open Browserはuiプレフィックスと紐づいています
 <ui:OpenBrowser AutomaticallyDownloadWebDriver="{x:Null}" BrowserType="{x:Null}" CommunicationMethod="{x:Null}" Hidden="{x:Null}" NewSession="{x:Null}" Private="{x:Null}" UiBrowser="{x:Null}" DisplayName="ブラウザーを開く" sap:VirtualizedContainerService.HintSize="467,237" sap2010:WorkflowViewState.IdRef="OpenBrowser_1" Url="https://www.apple.com/jp/">
      <ui:OpenBrowser.Body>
        <ActivityAction x:TypeArguments="x:Object">
          <ActivityAction.Argument>
            <DelegateInArgument x:TypeArguments="x:Object" Name="ContextTarget" />
          </ActivityAction.Argument>
          <Sequence DisplayName="実行" sap:VirtualizedContainerService.HintSize="416,89" sap2010:WorkflowViewState.IdRef="Sequence_2">
            <sap:WorkflowViewStateService.ViewState>
              <scg:Dictionary x:TypeArguments="x:String, x:Object">
                <x:Boolean x:Key="IsExpanded">True</x:Boolean>
              </scg:Dictionary>
            </sap:WorkflowViewStateService.ViewState>
          </Sequence>
        </ActivityAction>
      </ui:OpenBrowser.Body>

上記をご理解いただいた上で、以下のコードを使って名前空間を取得します。

コード

Dim uiNameSpace As System.Xml.Linq.XNameSpace
uiNameSpace = xDocument.Root.GetNamespaceOfPrefix("ui")

image.png

iv.条件分岐を配置します

まず、xmalファイルにより、uiの名前空間が必ずしも存在するわけではありません。そのため、uiの名前空間が存在しない場合、現在の繰り返しをスキップして、次のxmalにいかないとエラーになるので、「Else」のところに「繰り返しをスキップ」を配置します。

image.png

次に、uiの名前空間が存在する場合の処理は、「Then」の中で書きます。

v.「Then」を展開してコードを書きます

まず、uiの名前空間に所属するOpenBrowserの要素を取り出します。Descendantsのメソッドを使いますので、まだわからない方はPart 1をご参照ください。

コード
Dim elems As IEnumerable(Of XElement) = xDocument.Descendants(uiNameSpace+"OpenBrowser")

image.png

次に、一つのxamlファイルに複数のOpenBrowserが存在する場合、複数のOpenBrowser要素が返ってくるので、elemsをループして個々のOpenBrowserのURLを取得する必要があります。

コード
For Each currentXElement In elems
 Body3
Next

image.png

vi.Body3を展開してURLを取得します

URLはOpenBrowser要素のどこで書いてあるのかを確認しましょう。

URLの存在場所
 <ui:OpenBrowser 
 AutomaticallyDownloadWebDriver="{x:Null}"
 BrowserType="{x:Null}"
 CommunicationMethod="{x:Null}"
 Hidden="{x:Null}"
 NewSession="{x:Null}"
 Private="{x:Null}"
 UiBrowser="{x:Null}"
 DisplayName="ブラウザーを開く"
 sap:VirtualizedContainerService.HintSize="467,237"
 sap2010:WorkflowViewState.IdRef="OpenBrowser_1"
 Url="https://www.apple.com/jp/">

長いですが、<ui:OpenBrowser>に入っているので、Urlは<ui:OpenBrowser>の属
性ですね!そうしたら、Attributeのメソッドを使ってUrlを抽出してみましょう。

Body3の中身
Dim Url As String
Url = currentXElement.Attribute("Url").Value.ToString

抽出した後、xmal名と共にdtUrlInfoに行として追加します。

image.png

最後はdtUrlInfoを出力して結果を確認します。

image.png

終わりに

今回はxmalファイルをXDocumentに変換して中身の情報を抽出する方法をご紹介しました。活用シーンとしては、例えば、稼働中の数千本のプロセスから特定のURLに紐づくシステムの利用状況を洗い出すことが挙げられます。いちいちワークフローを開いて確認する必要はなく、わずか数秒で情報が入手できるため、ぜひ試してみてくださいね!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?