4

区切り文字で XML ノードを分解し、個々のノードを作成する XSLT 1.0 が必要です。たとえば、区切り文字が「_」で、XML が次の場合:

<root>
    <a_b_c>hello<a_b_c>
    <a_b_c1>world</a_b_c1>
</root>

結果の XML は次のようになります。

<root>
    <a>
        <b>
            <c>hello</c>
            <c1>world</c1>
        </b>
    </a>
</root>

デリミタを含まないノードは、そのまま出力する必要があります。XSLT1.0でこれが本当に必要です 助けてくれてありがとう。

4

1 に答える 1

2

この変換:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

  <xsl:key name="kSameNameAdj" match="*"
  use="concat(generate-id(..),
              '+',
              generate-id(preceding-sibling::*[not(name()=name(current()))][1])
              )"/>

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

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <xsl:apply-templates select="node()"/>
  </xsl:variable>

  <xsl:apply-templates select="ext:node-set($vrtfPass1)" mode="compress"/>
 </xsl:template>

 <xsl:template name="explode" match=
  "*[contains(name(),'_')
   and not(substring(name(),1,1)='_')
   and not(substring(name(), string-length(name()))='_')
    ]">
    <xsl:param name="pName" select="name()"/>
    <xsl:param name="pText" select="text()"/>

  <xsl:choose>
   <xsl:when test="not($pName)">
    <xsl:value-of select="$pText"/>
   </xsl:when>
   <xsl:otherwise>
      <xsl:element name="{substring-before(concat($pName, '_'), '_')}">
       <xsl:call-template name="explode">
         <xsl:with-param name="pName" select="substring-after($pName, '_')"/>
         <xsl:with-param name="pText" select="$pText"/>
       </xsl:call-template>
      </xsl:element>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

  <xsl:template match="/" name="fold" mode="compress">
  <xsl:param name="pDoc" select="/"/>

  <xsl:choose>
    <xsl:when test="not($pDoc//*[name()=name(following-sibling::*[1])])">
      <xsl:copy-of select="$pDoc"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="vrtfThisPass">
        <xsl:apply-templates select="$pDoc/*" mode="compress"/>
      </xsl:variable>

      <xsl:call-template name="fold">
        <xsl:with-param name="pDoc" select="ext:node-set($vrtfThisPass)"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="node()|@*" mode="compress">
   <xsl:copy>
     <xsl:apply-templates select="@*|node()[1]" mode="compress"/>
   </xsl:copy>
   <xsl:apply-templates select="following-sibling::node()[1]" mode="compress"/>
 </xsl:template>

 <xsl:template match="*[name()=name(following-sibling::*[1])]" mode="compress">
  <xsl:element name="{name()}">
    <xsl:apply-templates mode="compress" select=
    "key('kSameNameAdj',
          concat(generate-id(..),
                 '+',generate-id(preceding-sibling::*)
                 )
         )/node()"/>
  </xsl:element>
  <xsl:apply-templates mode="compress" select=
  "key('kSameNameAdj',
          concat(generate-id(..),
                 '+',generate-id(preceding-sibling::*)
                 )
         )
          [last()]/following-sibling::node()[1]
   "/>
 </xsl:template>
</xsl:stylesheet>

次の XML ドキュメントに適用した場合(提供されたもので、より困難になるように拡張されています):

<root>
   <x>This is:</x>
     <a_b_c>hello</a_b_c>
     <a_b_c_d>my</a_b_c_d>
     <a_b_c1>wonderful</a_b_c1>
     <a_b_c>world</a_b_c>
     <a_b>!</a_b>
   <y>The End</y>
</root>

必要な正しい結果が生成されます

<root>
   <x>This is:</x>
   <a>
      <b>
         <c>hello<d>my</d>
         </c>
         <c1>wonderful</c1>
         <c>world</c>!</b>
   </a>
   <y>The End</y>
</root>

説明:

.1. これはマルチパス変換です。最初のパスは、XML ドキュメントを次のように変換します。

<root>
   <x>This is:</x>
   <a>
      <b>
         <c>hello</c>
      </b>
   </a>
   <a>
      <b>
         <c>
            <d>my</d>
         </c>
      </b>
   </a>
   <a>
      <b>
         <c1>wonderful</c1>
      </b>
   </a>
   <a>
      <b>
         <c>world</c>
      </b>
   </a>
   <a>
      <b>!</b>
   </a>
   <y>The End</y>
</root>

.2. 後続のパスでは、それぞれが同じ名前を持つ隣接する要素のグループをその名前を持つ単一の要素に圧縮します。次に、同じ名前を持つ複数の隣接する兄弟要素のグループがなくなるまで、結果が再帰的に処理されます。

.3. 最初のパスでは、アイデンティティ ルールを使用します。

.4. 次のパスでは、「圧縮」モードで高品質の IDテンプレートを使用します。

于 2012-08-05T18:19:35.620 に答える