2017-02-13 15 views
-1

私はXSLT変換をとても新しくしました。 FPMLメッセージをより単純なXMLに変換してhrefとIDの種類の属性を削除する必要があります(対象システムでこのタイプの複合XMLが認識されません)他の要素をコピーしてhref要素を置換するXSLT変換

私の入力XMLこのようなものです

<fpml:partyTradeInformation> 
       <fpml:partyReference href="Party1"/> 
       <fpml:accountReference href="Book1"/> 
</fpml:partyTradeInformation> 

and in same xml at bottom is the Party1 reference 
    <party id="Party1"> 
     <fpml:partyId partyIdScheme="urn:abc:party-id:EMX-LOH">What is the partyName for PQR?</fpml:partyId> 
     <fpml:partyId partyIdScheme="urn:abc:party-id:PO_ID">PO19</fpml:partyId> 
     <fpml:partyId partyIdScheme="urn:abc:party-id:PO">PO19</fpml:partyId> 
     <fpml:partyId partyIdScheme="urn:abc:party-id:TREATS_ID">MNO</fpml:partyId> 
     <fpml:partyName>What is the partyName for PQR?</fpml:partyName> 
    </party> 

Now first i have to transform my party1 to like below which I am able to do 
    <Party1> 
     <EMX-LOH>What is the partyName for ABC?</EMX-LOH> 
     <PO_ID>PO19</PO_ID><PO>PO19</PO> 
     <PO>PO19</PO> 
     <TREATS_ID>XYZ</TREATS_ID> 
     <partyName xmlns="">What is the partyName for ABC?</partyName> 
    </Party1> 

But then i have to also replace my <fpml:partyReference href="Party1"/> like 
<partyReference> 
    <party> 
     <Party1> 
      <EMX-LOH>What is the partyName for ABC?</EMX-LOH> 
      <PO_ID>PO19</PO_ID><PO>PO19</PO> 
      <PO>PO19</PO> 
      <TREATS_ID>XYZ</TREATS_ID> 
      <partyName xmlns="">What is the partyName for ABC?</partyName> 
     </Party1> 
    </party> 
</partyReference > 

hrefインスタンスで変換されたParty1セットをコピーするにはどうすればよいですか? また、XSLT変換された要素であるParty1のテンプレートマッチをしようとすると、パーサーはそれを認識できません。しかし、要素パーティ(元のもの)と一致すると、パーサはそれを認識することができます。

+0

質問が不明です。 XML、現在のXSLT、期待される出力を含む[mcve]を投稿してください。 - 私はあなたが[キー](https://www.w3.org/TR/xslt/#key)の使い方を学びたいと思っています。 –

答えて

0

パーティーhrefを対応するパーティー要素に置き換えるXSLTがここにあります。私はあなたのfpmlプレフィックスが、私はその名前空間のためにいくつかのサンプルURIに入れるに結合するのか分からないどのように見て

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:fpml="http://www.example.com"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="fpml:partyReference[@href]"> 
     <xsl:variable name="href" select="@href" /> 
     <partyReference> 
      <party> 
       <xsl:apply-templates select="//party[@id=$href]" mode="dereference" /> 
      </party> 
     </partyReference> 
    </xsl:template> 

    <xsl:template match="party" /> 

    <xsl:template match="party" mode="dereference"> 
     <xsl:element name="{@id}"> 
      <xsl:apply-templates select="node()|@*[not(local-name()='id')]" /> 
     </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 

node()|@*と一致する最初のテンプレートは、他のテンプレートと一致しないものだけをコピーする標準的なアプローチです。

と一致する2番目のテンプレートは、(特定の名前空間内の)href属性を持つ任意のpartyReferenceを取得し、@ hrefの値を変数に抽出し、id属性がそのhref値と一致するパーティー要素にテンプレートを適用します。 "dereference"という名前のモードがどのように導入されているかに注目してください。その名前は任意で、私が選んだものです。

次は、すべてのparty要素に一致し、何もしない空のテンプレートです。彼らはコピーされません。これにより、パーティーがすでに参照に登録された後に再びパーティをコピーすることが回避されます。

最終的にpartyのすべての要素に一致するテンプレートですが、モードがdereferenceの場合のみです。これにより、id属性の名前に新しい要素が作成され、id属性を除き属性と子ノードにテンプレートが適用されます(出力にコピーしないので)。これは、コンテンツのコピーをデフォルトにします。

あなたの入力にある属性が何であるかについての十分な情報がないため、私はそれらの内容を変換していません。上記はあなたにこれを解決する方法のいくつかの兆候を与えるはずです。接頭辞fpmlの正しいネームスペースを使用してXSLTを変更する必要があります。また、XML抽出がネームスペースの内容をあいまいにしているため、ネームスペースの使用方法を変更する必要があります。 XML文書で抽出するのではなく、それを理解する)。

また、XSLT変換要素であるParty1のテンプレートマッチを試みると、パーサーはそれを認識できません。しかし、要素パーティ(元のもの)と一致すると、パーサはそれを認識することができます。

これは、XSLTが入力ドキュメントでのみ機能するためです。それは、入力を横断し、その部分をテンプレートにマッチさせ、それらのテンプレート内の命令を実行する。宣言的な言葉です。したがって、生成される出力は入力の一部ではなく、影響を与えません。それには複数のXSLT変換が必要です。

あなたが提供しているXMLは、XIncludeやその他の参照スキームなどのいくつかの技術を利用する可能性があります。適切なテクノロジをサポートするパーサーやそのような参照スキームを実装するライブラリを使用して、結果を得ることができる場合があります。そのため、XSLTを使用する前に、既に行っていることがあるかどうかを確認してください。

EDIT:上記と同じ量のテンプレート内の複数の要素に一致する例。これは、入力XML内のid属性が、hrefによって参照されるすべての要素に対して一意である場合にのみ機能することに注意してください。そうしないと、結果が正しくない可能性があります。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
    xmlns:fpml="http://www.example.com"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="fpml:partyReference[@href]|fpml:accountReference[@href]|fpml:payerPartyReference[@href]"> 
     <xsl:variable name="href" select="@href" /> 
     <xsl:element name="{local-name()}" namespace="{namespace-uri()}"> 
      <xsl:apply-templates select="//*[@id=$href]" mode="dereference" /> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="party|account|payerParty" /> 

    <xsl:template match="party|account|payerParty" mode="dereference"> 
     <xsl:element name="{local-name()}" namespace="{namespace-uri()}"> 
      <xsl:element name="{@id}"> 
       <xsl:apply-templates select="node()|@*[not(local-name()='id')]" /> 
      </xsl:element> 
     </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 
+0

完璧!ありがとう。これは私が探していたものです。名前空間はターゲットxmlでは必須ではありません。そこで、入力自体から取り除くことを考えます。 – rashb

+0

@rashbこれで問題を解決できる場合は、スコアの下のチェックマークをクリックして答えとして受け入れることを検討してください。これは、それが他のユーザーに役立ち、評判を提供する正解であると考えていることを示しています。後でより良い回答を投稿する必要がある場合でも、受け入れる回答を変更することができます。 –

+0

@rashbはい、これが可能です。難しい部分は、 ''の部分に何を入れるかを知ることです。 「パーティー」だけではなく、正しい要素でなければならないだろう。しかし、href属性が異なるタイプであっても一意であることが保証されていれば、これを使うことができます: '' 'を参照し、逆参照モードでテンプレートを調整します。それは 'party | account | payerParty ...'のようなものを使用して、それだけが考慮されることを確認するか、ワイルドカードです。 –

関連する問題