0

XML メッセージの一部の要素を変換できません。いくつかの値を交換する必要がありますが、最後のノードの値を最初のノードにコピーした後、最初のノードの元の値に到達できません。

私は何時間も検索しており、XSL 内でいくつかのバリエーションを試しましたが、満足のいく結果は得られませんでした。私は経験豊富な XSL プログラマーではありませんが、解決策はそれほど難しくないと思います。問題を説明するために元のメッセージを簡略化しました。どなたかがこの問題について私を助けてくれることを願っています。次の例で説明しましょう。

ソース:

<ProcessMessages>
  <Message>
    <SomeNode>Val</SomeNode>
    <SomeNode>Val</SomeNode>
    <Number>100000</Number>
    <ExternalRefID>EXX12345600000001</ExternalRefID>
    <SomeNode>Val</SomeNode>
    <SomeNode>Val</SomeNode>
  </Message>
  <RelatedMessages>
    <Message>     
      <SomeNode>Val</SomeNode>
      <Number>200000</Number>
      <ExternalRefID>EXX12345600000002</ExternalRefID>
      <SomeNode>Val</SomeNode>
    </Message>
    <Message>
      <SomeNode>Val</SomeNode>
      <Number>300000</Number>
      <ExternalRefID>EXX12345600000003</ExternalRefID>
      <SomeNode>Val</SomeNode>
    </Message>
  </RelatedMessages>
</ProcessMessages>

望ましい変換:

<ProcessMessages>
  <Message>
    <SomeNode>Val</SomeNode>
    <SomeNode>Val</SomeNode>
    <ExternalRefID>EXX12345600000003</ExternalRefID>
    <SomeNode>Val</SomeNode>
    <SomeNode>Val</SomeNode>
  </Message>
  <RelatedMessages>
    <Message>     
      <Number>200000</Number>
      <ExternalRefID>EXX12345600000002</ExternalRefID>
    </Message>
    <Message>
      <Number>100000</Number>
      <ExternalRefID>EXX12345600000001</ExternalRefID>
    </Message>
  </RelatedMessages>
</ProcessMessages>

私のXSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

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

<xsl:template match="//ProcessMessages/Message/ExternalRefID">
    <xsl:apply-templates select="//ProcessMessages/RelatedMessages/Message[last()]/ExternalRefID"/>
  </xsl:template>
  <xsl:template match="//ProcessMessages/Message/Number">
    <xsl:apply-templates select="//ProcessMessages/RelatedMessages/Message[last()]/Number"/>
  </xsl:template>

  <xsl:template match="//ProcessMessages/RelatedMessages/Message[1]">
    <xsl:element name="Message">
      <xsl:apply-templates select="ExternalRefID"/>
      <xsl:apply-templates select="Number"/>
    </xsl:element>
  </xsl:template>
  <xsl:template match="//ProcessMessages/RelatedMessages/Message[2]">
    <xsl:element name="Message">
      <xsl:apply-templates select="//ProcessMessages/Message/ExternalRefID"/>
      <xsl:apply-templates select="//ProcessMessages/Message/Number"/>
    </xsl:element>
  </xsl:template>  
</xsl:stylesheet>

現在の結果

<ProcessMessages>
  <Message>
    <SomeNode>Val</SomeNode>
    <SomeNode>Val</SomeNode>
    <Number>100000</Number>
    <ExternalRefID>EXX12345600000001</ExternalRefID>
    <SomeNode>Val</SomeNode>
    <SomeNode>Val</SomeNode>
  </Message>
  <RelatedMessages>
    <Message>
      <ExternalRefID>EXX12345600000002</ExternalRefID>
      <Number>200000</Number>
    </Message>
    <Message>
      <ExternalRefID>EXX12345600000001</ExternalRefID>
      <Number>100000</Number>
    </Message>
  </RelatedMessages>
</ProcessMessages>

ProcessMessages/RelatedMessages/Messageの値をにコピーした後、上書きされているように見えるためProcessMessages/Message、 のデフォルト値に到達できないことに注意してください。ProcessMessages/Message

何か案は?誰かが私を助けることができれば、私はとても感謝しています!

4

1 に答える 1

0

いいえ、入力で何も上書きしていません。XSLT 変換の出力ツリーは入力とは別のオブジェクトであり、入力は可変ではありません。入力内の何も上書きまたは変更されることはありません。

はい、あなたは正しいです。あなたの問題には簡単な解決策があります。

問題は、/ProcessMessages/Message の ExternalRefID と Number を RelatedMessages 要素の末尾にコピーしようとすると、次のような形式になることです。

<xsl:apply-templates 
  select="//ProcessMessages
           /Message/ExternalRefID"/>
<xsl:apply-templates 
  select="//ProcessMessages
           /Message/Number"/>

スタイルシート エンジンは要求どおりに動作し、それらの要素のテンプレートを探します。サンプル コード内の 2 番目と 3 番目のテンプレート (関連メッセージの最後のメッセージ要素から値を探してコピーするテンプレート) を見つけます。

構築しようとしている変換を正確に定義する方法は完全には明らかではありませんが、(1) RelatedMessages の最終メッセージを ProcessMessages の最初の子に移動し、(2) ProcessMessages の最初の子を RelatedMessages の最後に移動すると、次のようになります。

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

<xsl:template match="ProcessMessages">
  <xsl:copy-of 
    select="RelatedMessages/Message[last()]"/>
  <xsl:apply-templates select="RelatedMessages"/>
</xsl:template>

<xsl:template 
  match="RelatedMessages/Message[last()]">
  <xsl:copy-of 
    select="../../self::ProcessMessages
            /Message[1]"/>
</xsl:template>  

Number と ExternalRefIDのみを変更する場合は、このコードを適切に変更する必要があります。

于 2012-09-20T23:15:53.393 に答える