1

文字列ルックアップを行う方法と、カンマ区切りの文字列をそれぞれ解析する方法を考えました。しかし、これら2つの要件の両方を満たす効率的な方法があるのだろうか. ソース XML は次のとおりです。

<?xml version="1.0" ?>
     <MATRIX>
     <DATA_RECORD>
      <COMPONENT1>1, 2</COMPONENT1> 
      <COMPONENT2>6, 7, 8, 9</COMPONENT2>  
     </DATA_RECORD>
    </MATRIX>

コンマ区切りの文字列を解析し、各トークンを使用してルックアップを行うことで、次の XML を生成することを期待しています。

<?xml version="1.0" encoding="UTF-8"?>
     <MATRIX>
     <DATA_RECORD>
      <COMPONENT1>A, B</COMPONENT1> 
      <COMPONENT2>F, G, H, I</COMPONENT2>  
     </DATA_RECORD>
    </MATRIX>

これが私のルックアップXML(COMPONENT_LOOKUPLIST.xml)です:

<?xml version="1.0" ?>
    <MAIN>
      <DATA_RECORD>
        <COMPONENT_ID>1</COMPONENT_ID>
        <COMPONENT_NAME>A</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>2</COMPONENT_ID>
        <COMPONENT_NAME>B</COMPONENT_NAME>    
      </DATA_RECORD>
        <DATA_RECORD>
        <COMPONENT_ID>3</COMPONENT_ID>
        <COMPONENT_NAME>C</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>4</COMPONENT_ID>
        <COMPONENT_NAME>D</COMPONENT_NAME>    
      </DATA_RECORD>
        <DATA_RECORD>
        <COMPONENT_ID>5</COMPONENT_ID>
        <COMPONENT_NAME>E</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>6</COMPONENT_ID>
        <COMPONENT_NAME>F</COMPONENT_NAME>    
      </DATA_RECORD>
        <DATA_RECORD>
        <COMPONENT_ID>7</COMPONENT_ID>
        <COMPONENT_NAME>G</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>8</COMPONENT_ID>
        <COMPONENT_NAME>H</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>9</COMPONENT_ID>
        <COMPONENT_NAME>I</COMPONENT_NAME>    
      </DATA_RECORD>
    </MAIN>

私は XSLT の初心者です。XSLT の専門家がアイデアを共有したり、サンプル コードを提供したりできますか? Jeni の Web サイトからトークン コードを取得しました。

 <xsl:template name="tokenize">
          <xsl:param name="string" />
          <xsl:param name="delimiter" select="','" />
          <xsl:choose>
            <xsl:when test="$delimiter and contains($string, $delimiter)">
              <token>
                <xsl:value-of select="substring-before($string, $delimiter)" />
              </token>

              <xsl:call-template name="tokenize">
                <xsl:with-param name="string" 
                                select="substring-after($string, $delimiter)" />
                <xsl:with-param name="delimiter" select="$delimiter" />
              </xsl:call-template>
            </xsl:when>

            <xsl:otherwise>
              <token><xsl:value-of select="$string" /></token>

            </xsl:otherwise>
          </xsl:choose>
        </xsl:template>

    <xsl:call-template name="tokenize">    
            <xsl:with-param name="string" select="/MATRIX/DATA_RECORD/COMPONENT1"></xsl:with-param>
          </xsl:call-template>

            <xsl:call-template name="tokenize">    
            <xsl:with-param name="string" select="/MATRIX/DATA_RECORD/COMPONENT2"></xsl:with-param>
          </xsl:call-template>

そしてルックアップを書きました:

<xsl:variable name="lookup" select="document('COMPONENT_LOOKUPLIST.xml')/MAIN/DATA_RECORD"/>
                <xsl:for-each select="//DATA_RECORD">

 <token>
  <xsl:for-each select="*">      
   <xsl:value-of select="$lookup[COMPONENT_ID = current()]/COMPONENT_NAME"/>        
          </xsl:for-each>   
          </token>
        </xsl:for-each>

しかし、この 2 つを組み合わせるのは難しいようです。

ありがとうございました。

4

2 に答える 2

0

Saxon 9、AltovaXML、XmlPrime などの XSLT 2.0 プロセッサの使用を検討したことはありますか? その場合、たとえば簡単に行うことができます

<xsl:key name="by-id" match="DATA_RECORD" use="COMPONENT_ID"/>

<xsl:param name="lk-doc-url" select="'COMPONENT_LOOKUPLIST.xml'"/>
<xsl:variable name="lk-doc" select="document($lk-doc-url)"/>

<xsl:template match="*[starts-with(local-name(), 'COMPONENT')]">
  <xsl:copy>
    <xsl:value-of select="for $id in tokenize(., ', ') return key('by-id', $id, $lk-doc)/COMPONENT_NAME"
       separator=", "/>
  </xsl:copy>
</xsl:template>

[編集] 完全でテスト済みのサンプルは次のとおりです。

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">



<xsl:key name="by-id" match="DATA_RECORD" use="COMPONENT_ID"/>

<xsl:param name="lk-doc-url" select="'test2013013103.xml'"/>
<xsl:variable name="lk-doc" select="document($lk-doc-url)"/>

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

<xsl:template match="*[starts-with(local-name(), 'COMPONENT')]">
  <xsl:copy>
    <xsl:value-of select="for $id in tokenize(., ', ') return key('by-id', $id, $lk-doc)/COMPONENT_NAME"
       separator=", "/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

それをSaxon 9.4で入力に適用すると

<?xml version="1.0" ?>
     <MATRIX>
     <DATA_RECORD>
      <COMPONENT1>1, 2</COMPONENT1> 
      <COMPONENT2>6, 7, 8, 9</COMPONENT2>  
     </DATA_RECORD>
    </MATRIX>

ルックアップファイルtest2013013103.xml

<?xml version="1.0" ?>
    <MAIN>
      <DATA_RECORD>
        <COMPONENT_ID>1</COMPONENT_ID>
        <COMPONENT_NAME>A</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>2</COMPONENT_ID>
        <COMPONENT_NAME>B</COMPONENT_NAME>    
      </DATA_RECORD>
        <DATA_RECORD>
        <COMPONENT_ID>3</COMPONENT_ID>
        <COMPONENT_NAME>C</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>4</COMPONENT_ID>
        <COMPONENT_NAME>D</COMPONENT_NAME>    
      </DATA_RECORD>
        <DATA_RECORD>
        <COMPONENT_ID>5</COMPONENT_ID>
        <COMPONENT_NAME>E</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>6</COMPONENT_ID>
        <COMPONENT_NAME>F</COMPONENT_NAME>    
      </DATA_RECORD>
        <DATA_RECORD>
        <COMPONENT_ID>7</COMPONENT_ID>
        <COMPONENT_NAME>G</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>8</COMPONENT_ID>
        <COMPONENT_NAME>H</COMPONENT_NAME>    
      </DATA_RECORD>
      <DATA_RECORD>
        <COMPONENT_ID>9</COMPONENT_ID>
        <COMPONENT_NAME>I</COMPONENT_NAME>    
      </DATA_RECORD>
    </MAIN>

出力は

<?xml version="1.0" encoding="UTF-8"?><MATRIX>
     <DATA_RECORD>
      <COMPONENT1>A, B</COMPONENT1>
      <COMPONENT2>F, G, H, I</COMPONENT2>
     </DATA_RECORD>
    </MATRIX>

したがって、私の提案は機能します。コンテンツが得られない場合の違いはわかりません。

于 2013-01-31T17:11:22.307 に答える
0

XSLT1.0 に行き詰まっている場合、1 つの解決策は、トークン要素を吐き出すのではなく、ルックアップを行うようにトークン化テンプレートを修正することです(トークン要素をそのままにしておく場合は、2 パス変換を行う必要があります)。ルックアップに基づいてこれらを文字列に変換します)。

したがって、トークン化テンプレートでこれを行う代わりに

<token>
   <xsl:value-of select="substring-before($string, $delimiter)" />
</token>

代わりにこれをしてください

<xsl:value-of select="$lookup[COMPONENT_ID=normalize-space(substring-before($string, $delimiter))]/COMPONENT_NAME"/>
 <xsl:value-of select="$delimiter"/>

ここに完全な XSLT があります

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output omit-xml-declaration="yes" method="html"/>

   <xsl:variable name="lookup" select="document('C:\COMPONENT_LOOKUPLIST.xml')/MAIN/DATA_RECORD"/>

   <xsl:template match="DATA_RECORD/*">
      <xsl:copy>
         <xsl:call-template name="tokenize">
            <xsl:with-param name="string" select="."/>
         </xsl:call-template>
      </xsl:copy>
   </xsl:template>

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

   <xsl:template name="tokenize">
      <xsl:param name="string"/>
      <xsl:param name="delimiter" select="','"/>
      <xsl:choose>
         <xsl:when test="$delimiter and contains($string, $delimiter)">
            <xsl:value-of select="$lookup[COMPONENT_ID=normalize-space(substring-before($string, $delimiter))]/COMPONENT_NAME"/>
            <xsl:value-of select="$delimiter"/>
            <xsl:call-template name="tokenize">
               <xsl:with-param name="string" select="substring-after($string, $delimiter)"/>
               <xsl:with-param name="delimiter" select="$delimiter"/>
            </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
            <xsl:value-of select="$lookup[COMPONENT_ID=normalize-space($string)]/COMPONENT_NAME"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

XML に適用すると、以下が出力されます。

<MATRIX>
   <DATA_RECORD>
      <COMPONENT1>A,B</COMPONENT1>
      <COMPONENT2>F,G,H,I</COMPONENT2>
   </DATA_RECORD>
</MATRIX>

これによりスペースも削除されますが、問題にならないことを願っています...

編集:スペースを保持したい場合は、次のようにします。

<xsl:variable name="current" select="substring-before($string, $delimiter)" />
<xsl:value-of select="substring-before($current, normalize-space($current))" /> 
<xsl:value-of select="$lookup[COMPONENT_ID=normalize-space($)]/COMPONENT_NAME"/>
<xsl:value-of select="substring-after($current, normalize-space($current))" />
于 2013-01-31T17:21:30.977 に答える