0

私は約1.5か月間XSLTで自分自身をトレーニングしています。私は、私が理解するのに苦労しているものの簡略化された短いバージョンを作成しました、そして私が問題に固執しているので、どんな助けでも大いに感謝します。ありがとう!

基本的な状況:

要素定義xpathの祖先を持つroot属性に文字列があります:

/v3:QualityMeasureDocument/v3:component/v3:dataCriteriaSection/v3:definition/v3:valueSet/v3:id/@root

...要素エントリの祖先であるvalueSet属性のIDと一致すると、xpath:

/v3:QualityMeasureDocument/v3:component/v3:dataCriteriaSection/v3:entry/v3:observationCriteria/v3:value/@valueSet

また

/v3:QualityMeasureDocument/v3:component/v3:dataCriteriaSection/v3:entry/v3:observationCriteria/v3:code/@valueSet

出力(必要であり、現在はそうです)には、文字列とその必要な属性が表示されます。

ただし、これらの場所に文字列に一致するものがない場合は、文字列も「指定なし」ヘッダーでリストする必要があります。

エラー: 既存の文字列がすべて一致している場合でも、「指定されていません」ヘッダーとその文字列が一覧表示されます。このシナリオでは、一致する文字列のみがリストされている必要があります。

問題翻訳者(XSLファイル):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xalan="http://xml.apache.org/xalan"
  xmlns:v3="urn:hl7-org:v3"
  xmlns:rvs="urn:ihe:iti:svs:2008">  
  <xsl:output method="html" standalone="yes" omit-xml-declaration="no" indent="yes" xalan:indent-amount="2"/>    

  <xsl:template 
    match="/v3:QualityMeasureDocument">
    <html>
      <head>
        <title>Test 'I'</title>
      </head>
      <body>
        <ul>
          <xsl:apply-templates select="//v3:dataCriteriaSection" />
        </ul>
      </body>
    </html>  
  </xsl:template>

  <xsl:template
    match="v3:dataCriteriaSection">    
    <xsl:for-each select="//v3:entry">      
      <xsl:if test="*/v3:value/@valueSet">                    
        <xsl:call-template name="definitionValueSet">
          <xsl:with-param name="cur_valueSetID" select="*/v3:value/@valueSet"/> 
        </xsl:call-template>        
      </xsl:if>      
      <xsl:if test="*/v3:code/@valueSet">               
        <xsl:call-template name="definitionValueSet">
          <xsl:with-param name="cur_valueSetID" select="*/v3:code/@valueSet"/> 
        </xsl:call-template>        
      </xsl:if>      
      <xsl:if test="*/v3:participant/v3:roleParticipant/v3:code/@valueSet">                     
        <xsl:call-template name="definitionValueSet">
          <xsl:with-param name="cur_valueSetID" select="*/v3:participant/v3:roleParticipant/v3:code/@valueSet"/> 
        </xsl:call-template>        
      </xsl:if>                  
    </xsl:for-each>                
  </xsl:template>

  <xsl:template
    name="definitionValueSet">  
    <xsl:param name="cur_valueSetID"/>                     
    <xsl:for-each select="//v3:valueSet">                                
      <xsl:choose>    
        <xsl:when test="$cur_valueSetID != v3:id/@root or
        not( v3:text/v3:reference[starts-with(@value, 'https://') and contains(@value, $cur_valueSetID)] ) or
        not( v3:text/rvs:RetrieveValueSetResponse/rvs:ValueSet/@id = $cur_valueSetID )">   
          <xsl:if test="not($cur_valueSetID = '')">                                                    
            <li>
            <xsl:text>Not Specified</xsl:text>                                     
              <ul>
                <li>                       
                <xsl:text>ValueSet: </xsl:text>
                <xsl:value-of select="$cur_valueSetID"></xsl:value-of> 
                </li>
              </ul>
            </li>                 
          </xsl:if>
        </xsl:when>
        <xsl:when test="v3:id/@root = $cur_valueSetID"> 
          <xsl:if test="v3:text/v3:reference[starts-with(@value, 'https://') and contains(@value, $cur_valueSetID)]">
            <xsl:if test="v3:text/rvs:RetrieveValueSetResponse/rvs:ValueSet/@id = $cur_valueSetID">                 
              <li>       
                <xsl:text>Id: </xsl:text>
                <xsl:value-of select="v3:id/@root"/>                               
                <xsl:for-each select="v3:text/rvs:RetrieveValueSetResponse/rvs:ValueSet/rvs:ConceptList/rvs:Concept">
                  <ul>
                    <li>
                      <xsl:if test="not(@code = '')">
                        <xsl:if test="@code">
                          <xsl:text>code = </xsl:text>
                          <xsl:value-of select="@code"></xsl:value-of>
                          <xsl:text> </xsl:text>
                        </xsl:if>
                      </xsl:if>
                    </li>
                  </ul>        
                </xsl:for-each>
              </li>
            </xsl:if>
          </xsl:if>
        </xsl:when>    
      </xsl:choose>    
    </xsl:for-each>
  </xsl:template>                      
</xsl:stylesheet>

XML入力ファイル'I'xml:

<?xml version="1.0" encoding="UTF-8"?>
<QualityMeasureDocument xmlns="urn:hl7-org:v3">
  <component>
    <dataCriteriaSection>
      <definition>
        <valueSet>
          <!-- Value Set for Race -->
          <id root='1.1.1.1.1.1.1' />
          <text>
            <reference
              value='https://localhost/RetrieveValueSet?id=1.1.1.1.1.1.1' />
            <RetrieveValueSetResponse xmlns="urn:ihe:iti:svs:2008">
              <ValueSet id="1.1.1.1.1.1.1">
                <ConceptList>
                  <Concept code="4" />
                  <Concept code="5" />
                  <Concept code="6" />
                </ConceptList>
              </ValueSet>
            </RetrieveValueSetResponse>
          </text>
        </valueSet>
      </definition>
      <definition>
        <valueSet>
          <id root='1.1.1.1.1.1.2' />
          <text>
            <reference
              value='https://localhost/RetrieveValueSet?id=1.1.1.1.1.1.2' />
            <RetrieveValueSetResponse xmlns="urn:ihe:iti:svs:2008">
              <ValueSet id="1.1.1.1.1.1.2">
                <ConceptList>
                  <Concept code="007.2" />
                  <Concept code="007.3" />
                </ConceptList>
              </ValueSet>
            </RetrieveValueSetResponse>
          </text>
        </valueSet>
      </definition>
      <entry>
        <observationCriteria>
          <code code="424144002" codeSystem="123123213"
            displayName="FEWFW" />
          <value>
            <low />
            <high />
          </value>
        </observationCriteria>
      </entry>
      <entry>
        <observationCriteria>
          <code code="DFHKJ" codeSystem="ASKJDHK" displayName="ASDNJK" />
          <value>
            <width />
          </value>
        </observationCriteria>
      </entry>
      <entry>
        <observationCriteria>
          <code code="FDSFD" codeSystem="JHBHJB" displayName="HJGJH" />
          <value valueSet="1.1.1.1.1.1.1" />
        </observationCriteria>
      </entry>
      <entry>
        <encounterCriteria>
          <code valueSet="1.1.1.1.1.1.2" />
        </encounterCriteria>
      </entry>
    </dataCriteriaSection>
  </component>
</QualityMeasureDocument>

期待される出力コード'I'HTML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<html xmlns:xalan="http://xml.apache.org/xalan" xmlns:rvs="urn:ihe:iti:svs:2008" xmlns:v3="urn:hl7-org:v3">
  <head>
    <title>Test 'I'</title>
  </head>
  <body>
    <ul>
      <li>Id: 1.1.1.1.1.1.1
        <ul>
          <li>code = 4 </li>
        </ul>
        <ul>
          <li>code = 5 </li>
        </ul>
        <ul>
          <li>code = 6 </li>
        </ul>
      </li>
      <li>Id: 1.1.1.1.1.1.2
        <ul>
          <li>code = 007.2 </li>
        </ul>
        <ul>
          <li>code = 007.3 </li>
        </ul>
      </li>
    </ul>
  </body>
</html>

ハックやコードの消去によって正しい出力を作成するのは簡単ですが、これはすべての状況で機能する必要があります。たとえば、一致するものがまったくなく、発生するたびに「指定されていない」ヘッダーとその文字列のみが表示される場合や、両方の状況が混在している場合などです。このコードは現在、一致するものがない状況で機能し、「指定されていません」ヘッダーとその文字列が発生するたびに表示されます。

これができれば、「一致せず、まだリストされていない場合」、問題は解決するようです。

お役に立てば幸いです。より多くの情報またはより多くのファイルが必要な場合は私に知らせてください。どんなヒントも素晴らしいでしょう!ありがとう。

4

2 に答える 2

0

以下は、理解のために提供されている単純な代替ソリューション(generate-id()またはkey()を使用しない)です。ティムCの優れた答えよりも効率が悪く、置き換えられるべきではありません。私は単にこれを提供して、人々が学ぶことができるようにし、必要なものを手に入れて先に進むのではなく、この問題の解決に全力を注いでいることを示しています。

解決策は、元の「問題の翻訳者」を修正することです。そのXSLファイルから(大幅にではありますが)編集する必要がある唯一のセクションは、「definitionValueSet」という名前のテンプレートです。

最初に、後で個別に参照できるように、v3:id / @rootのすべての値を1回のパスで格納する変数$valueSetDataを作成する必要があります。この変数には、「、」が含まれます。これは、新しい一時データベースのようなものです。 for-eachには、要件に従って一致を制限する述語が含まれています。これらはローカルノードであるため、宣言に含まれています。また、これにより、後で余分な条件付きチェックが処理されなくなります。

<xsl:variable name="valueSetData">
   <xsl:for-each select="//v3:valueSet[
                           v3:text/v3:reference[starts-with(@value, 'https://') and contains(@value, $cur_valueSetID)] and 
                           v3:text/rvs:RetrieveValueSetResponse/rvs:ValueSet/@id = $cur_valueSetID]">       
     <xsl:value-of select="v3:id/@root"/>
     <xsl:text>,</xsl:text>
   </xsl:for-each>
</xsl:variable>

次に、詳細に合わせて編集されたchooseステートメントがあります。このステートメントは、 $valueSetData 'データベース'内で$cur_valueSetIDに一致するものがあるかどうかを判別します。for-each述語は、重複する一致を制限します(コンテキストのために間違った値が追加されます)。

    <xsl:choose>    
      <xsl:when test="contains($valueSetData, $cur_valueSetID)"> 
        <xsl:for-each select="//v3:valueSet[$cur_valueSetID = v3:id/@root]">
          <!-- Display found matches which meet all requirements -->
        </xsl:for-each>
      </xsl:when>
      <xsl:otherwise>
        <!-- Display Not Specified -->
      </xsl:otherwise>                                                                            
    </xsl:choose>   

完全な「definitionValueSet」テンプレート:

  <xsl:template
    name="definitionValueSet">  
    <xsl:param name="cur_valueSetID"/>  
    <xsl:variable name="valueSetData">
       <xsl:for-each select="//v3:valueSet[
                               v3:text/v3:reference[starts-with(@value, 'https://') and contains(@value, $cur_valueSetID)] and 
                               v3:text/rvs:RetrieveValueSetResponse/rvs:ValueSet/@id = $cur_valueSetID]">       
         <xsl:value-of select="v3:id/@root"/>
         <xsl:text>,</xsl:text>
       </xsl:for-each>
    </xsl:variable>                                     
    <xsl:choose>    
      <xsl:when test="contains($valueSetData, $cur_valueSetID)"> 
        <xsl:for-each select="//v3:valueSet[$cur_valueSetID = v3:id/@root]">
          <li>       
            <xsl:text>Id: </xsl:text>
            <xsl:value-of select="v3:id/@root"/>                               
            <xsl:for-each select="v3:text/rvs:RetrieveValueSetResponse/rvs:ValueSet/rvs:ConceptList/rvs:Concept">
              <ul>
                <li>
                  <xsl:if test="not(@code = '')">
                    <xsl:if test="@code">
                      <xsl:text>code = </xsl:text>
                      <xsl:value-of select="@code"></xsl:value-of>
                      <xsl:text/>
                    </xsl:if>
                  </xsl:if>
                </li>
              </ul>        
            </xsl:for-each>
          </li>            
        </xsl:for-each>
      </xsl:when>
      <xsl:otherwise>
        <li>
          <xsl:text>Not Specified</xsl:text>                                     
          <ul>
            <li>                       
              <xsl:text>ValueSet: </xsl:text>
              <xsl:value-of select="$cur_valueSetID"></xsl:value-of> 
            </li>
          </ul>
        </li> 
      </xsl:otherwise>                                                                            
    </xsl:choose>   
  </xsl:template>
于 2012-08-27T21:40:23.577 に答える
0

あなたが抱えている主な問題は、名前付きテンプレート「definitionValueSet」内にあると思います。ここでは、 xsl:for-eachを使用してvalueSet要素をループします。

<xsl:for-each select="//v3:valueSet"> 

この中で、関連する属性が現在のパラメーターと一致するかどうかをテストし、一致するものが見つかった場合は、リストを出力します。ただし、すべてのvalueSet要素が検索されるため、1つが一致した場合でも、一致しない要素を処理することになり、一致しない場合のxsl:ifも呼び出されます。これにより、「未指定」が出力されます。

本当に行う必要があるのは、valueSet要素が存在する場合はそれだけに一致させ、一致するものが存在しない場合は、「指定なし」を出力することです。

これを行う1つの方法は、最初に、一致するvalueSet要素の一意のIDを保持する変数を作成することです。

<xsl:variable name="valueSet">
   <xsl:value-of select="generate-id(//v3:valueSet[v3:id/@root = $cur_valueSetID and v3:text/v3:reference[starts-with(@value, 'https://') and contains(@value, $cur_valueSetID)] and v3:text/rvs:RetrieveValueSetResponse/rvs:ValueSet/@id = $cur_valueSetID])"/>
</xsl:variable>

次に、これが設定されているかどうかをテストし、設定されている場合は、その要素のテンプレートを適用します。設定されていない場合は、指定されていないコードを使用できます

<xsl:choose>
   <xsl:when test="$valueSet">
      <xsl:apply-templates select="//v3:valueSet[generate-id() = $valueSet]"/>
   </xsl:when>
   <xsl:otherwise>
      <!-- Not Specified -->
   </xsl:otherwise>
</xsl:choose>

これが完全なXSLTであり、必要な出力が得られることを願っています。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xalan" xmlns:v3="urn:hl7-org:v3" xmlns:rvs="urn:ihe:iti:svs:2008">
   <xsl:output method="html" standalone="yes" omit-xml-declaration="no" indent="yes" xalan:indent-amount="2"/>
   <xsl:template match="/v3:QualityMeasureDocument">
      <html>
         <head>
            <title>Test 'I'</title>
         </head>
         <body>
            <ul>
               <xsl:apply-templates select="//v3:dataCriteriaSection"/>
            </ul>
         </body>
      </html>
   </xsl:template>
   <xsl:template match="v3:dataCriteriaSection">
      <xsl:for-each select=".//v3:entry">
         <xsl:if test="*/v3:value/@valueSet">
            <xsl:call-template name="definitionValueSet">
               <xsl:with-param name="cur_valueSetID" select="*/v3:value/@valueSet"/>
            </xsl:call-template>
         </xsl:if>
         <xsl:if test="*/v3:code/@valueSet">
            <xsl:call-template name="definitionValueSet">
               <xsl:with-param name="cur_valueSetID" select="*/v3:code/@valueSet"/>
            </xsl:call-template>
         </xsl:if>
         <xsl:if test="*/v3:participant/v3:roleParticipant/v3:code/@valueSet">
            <xsl:call-template name="definitionValueSet">
               <xsl:with-param name="cur_valueSetID" select="*/v3:participant/v3:roleParticipant/v3:code/@valueSet"/>
            </xsl:call-template>
         </xsl:if>
      </xsl:for-each>
   </xsl:template>

   <xsl:template name="definitionValueSet">
      <xsl:param name="cur_valueSetID"/>
      <xsl:variable name="valueSet">
         <xsl:value-of select="generate-id(//v3:valueSet[v3:id/@root = $cur_valueSetID and v3:text/v3:reference[starts-with(@value, 'https://') and contains(@value, $cur_valueSetID)] and v3:text/rvs:RetrieveValueSetResponse/rvs:ValueSet/@id = $cur_valueSetID])"/>
      </xsl:variable>
      <xsl:choose>
         <xsl:when test="$valueSet != ''">
            <xsl:apply-templates select="//v3:valueSet[generate-id() = $valueSet]"/>
         </xsl:when>
         <xsl:otherwise>
            <li>
               <xsl:text>Not Specified</xsl:text>
               <ul>
                  <li>
                     <xsl:text>ValueSet: </xsl:text>
                     <xsl:value-of select="$cur_valueSetID"/>
                  </li>
               </ul>
            </li>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>

   <xsl:template match="v3:valueSet">
      <li>
         <xsl:text>Id: </xsl:text>
         <xsl:value-of select="v3:id/@root"/>
         <xsl:for-each select="v3:text/rvs:RetrieveValueSetResponse/rvs:ValueSet/rvs:ConceptList/rvs:Concept">
            <ul>
               <li>
                  <xsl:if test="not(@code = '')">
                     <xsl:if test="@code">
                        <xsl:text>code = </xsl:text>
                        <xsl:value-of select="@code"/>
                        <xsl:text/>
                     </xsl:if>
                  </xsl:if>
               </li>
            </ul>
         </xsl:for-each>
      </li>
   </xsl:template>
</xsl:stylesheet>

コメントで述べられているように、式の使用には注意してください//v3:entry。これは絶対式であり、ドキュメント内のすべての要素に一致します(つまり、ルート要素から下に向かって検索します)。現在の要素の下だけを見たい場合は、相対式を使用します.//v3:entry

編集:これのわずかな変形については、 valueSet要素を検索するための潜在的により効率的な方法として、XSLTドキュメントの上部にキーを定義できます

<xsl:key name="valueSet" match="v3:valueSet" use="generate-id()" />

次に、これを行う代わりに、正しいvalueSet要素を検索します

<xsl:apply-templates select="//v3:valueSet[generate-id() = $valueSet]"/>

代わりにキーを使用できます

<xsl:apply-templates select="key('valueSet', $valueSet)"/> 
于 2012-08-24T15:23:33.957 に答える