XML モジュールでの XPath の使用

<xml-module:xpath-extract> 操作は、XPath 式の評価をサポートしています。

XPath 式は各要素の任意の数値に一致する可能性があるため、この操作によって文字列のリストが返されます。要素が式に一致しない場合、この操作によって空のリストが返されます。

XPath 式も名前空間に対応しているため、この操作では名前空間のマッピングを使用できます。これらのマッピングは、参照される namespace-directory で定義される namespaces とマージされます。つまり、評価では両方の名前空間のマッピングのセットが組み合わされます。

MuleSoft は XPath 標準をサポートしていますが、DataWeave でも同じユースケースを実現でき、XML ドキュメントを抽出して変換するツールとして DataWeave をお勧めします。

次の例は、ウィリアム・シェイクスピアの戯曲『オセロ』の脚本を記載した XML を処理する方法を示しています。XML ファイルは次のようになります。

<?xml version="1.0"?>
<!--<!DOCTYPE PLAY SYSTEM "play.dtd">-->
<PLAY>
    <TITLE>The Tragedy of Othello, the Moor of Venice</TITLE>
    <FM>
        <P>Text placed in the public domain by Moby Lexical Tools, 1992.</P>
        <P>SGML markup by Jon Bosak, 1992-1994.</P>
        <P>XML version by Jon Bosak, 1996-1998.</P>
        <P>This work may be freely copied and distributed worldwide.</P>
    </FM>
    <PERSONAE>
        <TITLE>Dramatis Personae</TITLE>

        <PERSONA>DUKE OF VENICE</PERSONA>
        <PERSONA>BRABANTIO, a senator.</PERSONA>
        <PERSONA>Other Senators.</PERSONA>
        <PERSONA>GRATIANO, brother to Brabantio.</PERSONA>
        <PERSONA>LODOVICO, kinsman to Brabantio.</PERSONA>
        <PERSONA>OTHELLO, a noble Moor in the service of the Venetian state.</PERSONA>
        <PERSONA>CASSIO, his lieutenant.</PERSONA>
        <PERSONA>IAGO, his ancient.</PERSONA>
        <PERSONA>RODERIGO, a Venetian gentleman.</PERSONA>
        <PERSONA>MONTANO, Othello's predecessor in the government of Cyprus.</PERSONA>
        <PERSONA>Clown, servant to Othello. </PERSONA>
        <PERSONA>DESDEMONA, daughter to Brabantio and wife to Othello.</PERSONA>
        <PERSONA>EMILIA, wife to Iago.</PERSONA>
        <PERSONA>BIANCA, mistress to Cassio.</PERSONA>
        <PERSONA>Sailor, Messenger, Herald, Officers, Gentlemen, Musicians, and Attendants.</PERSONA>
    </PERSONAE>

    <SCNDESCR>SCENE  Venice: a Sea-port in Cyprus.</SCNDESCR>
    <PLAYSUBT>OTHELLO</PLAYSUBT>
    <ACT><TITLE>ACT I</TITLE>
    <SCENE><TITLE>SCENE I.  Venice. A street.</TITLE>
    <STAGEDIR>Enter RODERIGO and IAGO</STAGEDIR>
    <SPEECH>
        <SPEAKER>RODERIGO</SPEAKER>
        <LINE>Tush! never tell me; I take it much unkindly</LINE>
        <LINE>That thou, Iago, who hast had my purse</LINE>
        <LINE>As if the strings were thine, shouldst know of this.</LINE>
    </SPEECH>

.....
<!-- A LOT MORE CONTENT -->

ここで、全文が上記の形式のテキストがあるとします。次のスクリプトを使用して、handkerchief という単語が含まれるすべての行を抽出できます。

XPath スクリプト
<xml-module:xpath-extract xpath="//LINE[contains(., $word)]"> (1)
    <xml-module:context-properties>#[{'word': 'handkerchief'}]</xml-module:context-properties> (2)
</xml-module:xpath-extract>
1 $ プレフィックスを使用してコンテキストプロパティを参照する XPath 式を提供します。
2 context-properties パラメータで DataWeave を使用してコンテキストプロパティを生成します。

上記の XPath スクリプトにより、次の文字列のリストが出力されます。各 LINE はリストの異なる項目です。

出力
<LINE>For the same handkerchief?</LINE>
<LINE>What handkerchief?</LINE>
<LINE>What handkerchief?</LINE>
<LINE>Have you not sometimes seen a handkerchief</LINE>
<LINE>I know not that; but such a handkerchief--</LINE>
<LINE>Where should I lose that handkerchief, Emilia?</LINE>
<LINE>Lend me thy handkerchief.</LINE>
<LINE>That handkerchief</LINE>
<LINE>Fetch me the handkerchief: my mind misgives.</LINE>
<LINE>The handkerchief!</LINE>
<LINE>The handkerchief!</LINE>
<LINE>The handkerchief!</LINE>
<LINE>Sure, there's some wonder in this handkerchief:</LINE>
<LINE>But if I give my wife a handkerchief,--</LINE>
<LINE>But, for the handkerchief,--</LINE>
<LINE>Boding to all--he had my handkerchief.</LINE>
<LINE>--Handkerchief--confessions--handkerchief!--To</LINE>
<LINE>--Is't possible?--Confess--handkerchief!--O devil!--</LINE>
<LINE>mean by that same handkerchief you gave me even now?</LINE>
<LINE>By heaven, that should be my handkerchief!</LINE>
<LINE>And did you see the handkerchief?</LINE>
<LINE>That handkerchief which I so loved and gave thee</LINE>
<LINE>By heaven, I saw my handkerchief in's hand.</LINE>
<LINE>I saw the handkerchief.</LINE>
<LINE>It was a handkerchief, an antique token</LINE>
<LINE>O thou dull Moor! that handkerchief thou speak'st of</LINE>
<LINE>How came you, Cassio, by that handkerchief</LINE>

デフォルトでは、この操作はメッセージペイロードレベルで XML ドキュメントを変換しようとします。ただし、content パラメータを使用して入力ドキュメントを提供できます。

<flow name="linesFromOthello">
    <file:read path="othello.xml" target="othello" />
    <xml-module:xpath-extract xpath="//LINE[contains(., $word)]">
        <xml-module:content>#[vars.othello]</xml-module:content>
        <xml-module:context-properties>#[{'word': 'handkerchief'}]</xml-module:context-properties>
    </xml-module:xpath-extract>
</flow>

上記の例では、他の場所 (この場合、ファイルシステムのファイル) からコンテンツを取得し、シンプルな式を使用して参照しています。

名前空間のマッピング

入力 XML ドキュメントに名前空間が異なる要素が含まれている場合があります。たとえば、次のドキュメントについて考えます。

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body foo="bar">
    <ns1:echo xmlns:mule="http://simple.component.mule.org/">
      <ns1:echo>Hello!</ns1:echo>
    </ns1:echo>
  </soap:Body>
</soap:Envelope>

次の例では、XPath 式で使用される各 prefix を対応する名前空間 uri にマップします。

 <flow name="xpathWithInlineNs">
    <xml-module:xpath-extract xpath="/soap:Envelope/soap:Body/mule:echo/mule:echo">
        <xml-module:namespaces>
            <xml-module:namespace prefix="soap" uri="http://schemas.xmlsoap.org/soap/envelope/"/>
            <xml-module:namespace prefix="mule" uri="http://simple.component.mule.org/"/>
        </xml-module:namespaces>
    </xml-module:xpath-extract>
</flow>

しかし、同じ名前空間を使用する複数の XPath 式を実行する必要がある場合にはどうでしょうか? 毎回マッピングを実行せずに済むように、マッピングに namespace-directory を作成し、そのディレクトリを参照することができます。次に例を示します。

<xml-module:namespace-directory name="fullNs"> (1)
    <xml-module:namespaces>
        <xml-module:namespace prefix="soap" uri="http://schemas.xmlsoap.org/soap/envelope/"/>
        <xml-module:namespace prefix="mule" uri="http://simple.component.mule.org/"/>
    </xml-module:namespaces>
</xml-module:namespace-directory>

<flow name="xpathWithFullNs">
    <xml-module:xpath-extract
      xpath="/soap:Envelope/soap:Body/mule:echo/mule:echo"
      namespaceDirectory="fullNs"/> (2)(3)
</flow>
1 namespace-directory 要素を使用して、プレフィックスを実際の名前空間の URI にマップします。これらのプレフィックスは入力ドキュメントのプレフィックスに一致する必要があります。
2 続いて、これらのプレフィックスを XPath 式で参照できます。
3 最後に、namespaceDirectory パラメータを使用してステップ 1 で作成されたマッピングを参照します。

最後に、ユースケースを組み合わせることができます。たとえば、マッピングが含まれるグローバルな namespaceDirectory を用意して、操作レベルでマッピングを追加することができます。この組み合わせは、ドキュメントが多数あり、たとえば、そのすべてに soap 名前空間が含まれているが 1 つのドキュメントにしか mule 名前空間が含まれていない場合に便利です。

<xml-module:namespace-directory name="partialNs"> (1)
    <xml-module:namespaces>
        <xml-module:namespace prefix="soap" uri="http://schemas.xmlsoap.org/soap/envelope/"/>
    </xml-module:namespaces>
</xml-module:namespace-directory>

<flow name="xpathWithMergedNs">
    <xml-module:xpath-extract
      xpath="/soap:Envelope/soap:Body/mule:echo/mule:echo"
      namespaceDirectory="partialNs"> (2) (3)
        <xml-module:namespaces>
            <xml-module:namespace prefix="mule" uri="http://simple.component.mule.org/"/> (4)
        </xml-module:namespaces>
    </xml-module:xpath-extract>
</flow>
1 前と同じように namespace-directory を宣言しますが、共通の名前空間のみを指定します。
2 XPath 式を提供します。
3 部分的な名前空間ディレクトリを参照します。
4 追加のマッピングを提供します。

マッピングと XPath 式で使用されるプレフィックスが入力ドキュメントで使用されるプレフィックスに一致することが重要です。

関数としての XPath の使用

XML モジュールは、XPath を使用して値を抽出するための DataWeave 関数を提供します。これは、<choice> ルータや <foreach> ルータなどの場合に便利です。

この関数は任意の DataWeave 変換内でも使用できます。

<foreach> での XPath 関数の使用

オセロの行 の例に戻り、すべての行で反復し、個別に処理するとします。

<foreach collection="#[XmlModule::xpath('//LINE', payload, {})]">
    <flow-ref name="processLine" />
</foreach>
  • 最初の引数は XPath 式です。

  • 2 つ目の引数は入力ドキュメントで、この場合、メッセージペイロードです。

  • 3 つ目の引数はコンテキストプロパティです。この場合では何も必要ないため、関数は空のオブジェクトを渡します ({})。

<choice> での XPath 関数の使用

オセロの行 の例に戻り、入力ドキュメントに単語 handkerchief が含まれない場合に何かを実行するとします。

<choice>
    <when expression="#[isEmpty(XmlModule::xpath('//LINE[contains(., \$word)]', vars.untrustedOthello, {'word': 'handkerchief'}))]">
        <flow-ref name="alteredOthello" />
    </when>
</choice>
  • XmlModule::xpath 関数はリストを返すため、この例では DataWeave isEmpty() 関数を使用して出力が空かどうかをテストします。

  • XPath 関数の最初に引数は、$word コンテキストプロパティを使用する式です。

  • 2 つ目の引数は変数内の入力ドキュメントです。

  • 3 つ目の引数はコンテキストプロパティ値を提供します。

関連情報

Was this article helpful?

💙 Thanks for your feedback!

Edit on GitHub