1

更新:私はすべての助けに感謝します。Process elemタグを皆さんの助けを借りて機能させることができましたが、上司には新しい要件があります。要素を(削除するのではなく)新しい場所に移動し、要素番号を適切に配置する必要があります。もう一度ありがとう、あなたたちは最高です!

前の問題:

私はxsltを初めて使用するので、ご容赦ください。だからここに問題があります。私はこのxmlを持っています:

 <Process>
          <elem0>
             <pcode>xx<pcode>
          </elem0>
          <elem1>
             <pcode>xy<pcode>
          </elem1>
          <elem2>
             <pcode>ab<pcode>
          </elem2>
          <elem3>
             <pcode>AD<pcode>
          </elem3>               
    </Process>

そして、pcode value ='xy'の要素を消去する必要があります。これは、xsltで正常に実行されています。ただし、それを実行すると、要素(elem0 elem2 elem3)の名前にギャップがあることがわかります。

<Process>
      <elem0>
         <pcode>xx<pcode>
      </elem0>
      <elem2>
         <pcode>ab<pcode>
      </elem2>
      <elem3>
         <pcode>AD<pcode>
      </elem3>               
</Process>

になりたいです

<Process>
          <elem0>
             <pcode>xx<pcode>
          </elem0>
          <elem1>
             <pcode>ab<pcode>
          </elem1>
          <elem2>
             <pcode>AD<pcode>
          </elem2>               
    </Process> so it shows up properly in front end, but I am stuck. Tried sorting but didn't work. elem identifications are

変更するので、ある種のテンプレートを使用するのが難しくなります。アドバイスありがとうございます!

更新:一部の要素を削除するのではなく、新しい場所に移動するという新しい要件が追加されました。ご不便をおかけして申し訳ございませんが、何卒よろしくお願い申し上げます。

私はこのxmlを持っています:

 <Process>
          <elem0>
             <pcode>xx<pcode>
          </elem0>
          <elem1>
             <pcode>xy<pcode>
          </elem1>
          <elem2>
             <pcode>ab<pcode>
          </elem2>
          <elem3>
             <pcode>AD<pcode>
          </elem3>               
    </Process>

そして、pcode value ='xy'の要素をEdProcessにMOVE(erase-old required)する必要があります。これは、xsltで正常に実行されています。ただし、それを実行すると、要素(elem0 elem2 elem3)の名前にギャップがあることがわかります。また、EdProcessはelem0から開始する必要があり、移動される新しい要素はすべて順番に並んでいる必要があります。つまり、elem0、elem1、elem2などです。

<Process>
      <elem0>
         <pcode>xx<pcode>
      </elem0>
      <elem2>
         <pcode>ab<pcode>
      </elem2>
      <elem3>
         <pcode>AD<pcode>
      </elem3>               
</Process>



<EdProcess>
          <elem1>
             <pcode>xy<pcode>
          </elem1>
   </EdProcess>

になりたいです

<Process>
          <elem0>
             <pcode>xx<pcode>
          </elem0>
          <elem1>
             <pcode>ab<pcode>
          </elem1>
          <elem2>
             <pcode>AD<pcode>
          </elem2>               
    </Process>

 <EdProcess>
          <elem0>
             <pcode>xy<pcode>
          </elem0>
   </EdProcess>

フロントエンドに正しく表示されますが、行き詰まります。並べ替えを試しましたが、機能しませんでした。elemの識別が変更されているため、ある種のテンプレートを使用するのは難しくなっています。アドバイスありがとうございます!

4

5 に答える 5

2

ソース形式にsと混在する他の要素がないと仮定すると、elemこれを行うための非常に単純で簡単な方法があり、前後の兄弟またはダブルパスを必要としません。

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

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

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates select="*[pcode != 'xy']" mode="elems" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*" mode="elems">
    <xsl:element name="elem{position() - 1}">
      <xsl:apply-templates select="@* | node()" />
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

この入力に適用した場合:

<Process>
  <elem0>
    <pcode>xx</pcode>
  </elem0>
  <elem1>
    <pcode>xy</pcode>
  </elem1>
  <elem2>
    <pcode>ab</pcode>
  </elem2>
  <elem3>
    <pcode>xy</pcode>
  </elem3>
  <elem4>
    <pcode>AD</pcode>
  </elem4>
</Process>

生産:

<Process>
  <elem0>
    <pcode>xx</pcode>
  </elem0>
  <elem1>
    <pcode>ab</pcode>
  </elem1>
  <elem2>
    <pcode>AD</pcode>
  </elem2>
</Process>
于 2013-03-12T17:01:15.840 に答える
0

elemこれは、兄弟だけでなく、ツリー内の任意の場所に存在する可能性のあるN個の要素を正しく処理するワンパスソリューションです。他のどの回答も、そのようなXMLドキュメントを正しく処理しません。

それはかなり効率的です-木が限られた深さである場合、その効率は線形(O(N))に近いです。そのようなすべての要素が兄弟である場合、それ線形です:

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

 <xsl:template match="node()|@*">
  <xsl:param name="pCount" select="0"/>
  <xsl:copy>
   <xsl:apply-templates select="node()[1]|@*">
     <xsl:with-param name="pCount" select="$pCount"/>
   </xsl:apply-templates>
  </xsl:copy>
  <xsl:apply-templates select="following-sibling::node()[1]">
     <xsl:with-param name="pCount" select=
      "$pCount + count(.//*[starts-with(name(), 'elem') and not(pcode='xy')])"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="*[starts-with(name(), 'elem') and not(pcode='xy')]">
  <xsl:param name="pCount" select="0"/>
  <xsl:element name="elem{$pCount}">
   <xsl:apply-templates select="node()[1]|@*">
     <xsl:with-param name="pCount" select="$pCount+1"/>
   </xsl:apply-templates>
  </xsl:element>
  <xsl:apply-templates select="following-sibling::node()[1]">
     <xsl:with-param name="pCount" select=
     "$pCount+1+ count(.//*[starts-with(name(), 'elem') and not(pcode='xy')])"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="*[starts-with(name(), 'elem') and pcode='xy']">
  <xsl:param name="pCount" select="0"/>

  <xsl:apply-templates select="following-sibling::node()[1]">
     <xsl:with-param name="pCount" select="$pCount"/>
  </xsl:apply-templates>
 </xsl:template>
</xsl:stylesheet>

この変換が次のXMLドキュメントに適用される場合:

<Process>
  <a/>
  <elem0>
    <pcode>xx</pcode>
      <elem1>
        <pcode>xy</pcode>
      </elem1>
      <elem2>
        <pcode>xz</pcode>
      </elem2>
 </elem0>
  <b/>
  <elem3>
    <pcode>xy</pcode>
  </elem3>
  <c/>
  <elem4>
    <pcode>ab</pcode>
  </elem4>
  <d/>
  <elem5>
    <pcode>xy</pcode>
  </elem5>
  <e/>
  <elem6>
    <pcode>AD</pcode>
  </elem6>
  <f/>
</Process>

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

<Process>
   <a/>
   <elem0>
      <pcode>xx</pcode>
      <elem1>
         <pcode>xz</pcode>
      </elem1>
   </elem0>
   <b/>
   <c/>
   <elem2>
      <pcode>ab</pcode>
   </elem2>
   <d/>
   <e/>
   <elem3>
      <pcode>AD</pcode>
   </elem3>
   <f/>
</Process>
于 2013-03-13T03:26:06.483 に答える
0

XSLTは更新可能な変数を実行しないため、これを確認できる最も簡単なアプローチは、一度に1人の兄弟を処理する再帰テンプレートです。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/">
    <Process>
      <!-- start with the first child -->
      <xsl:apply-templates select="Process/*[pcode != 'xy'][1]" />
    </Process>
  </xsl:template>

  <xsl:template match="*">
    <xsl:param name="nextIndex" select="0" />
    <xsl:element name="elem{$nextIndex}">
      <xsl:copy-of select="node()" />
    </xsl:element>
    <!-- process the next applicable sibling, if any, incrementing the index -->
    <xsl:apply-templates select="following-sibling::*[pcode != 'xy'][1]">
      <xsl:with-param name="nextIndex" select="$nextIndex + 1" />
    </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>
于 2013-03-12T16:31:59.247 に答える
0

preceding-sibling軸を使用して、現在の要素の前にelem*表示される要素の数をカウントできます。次に、削除されたはずの数字を引くと、現在の数字が得られます。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Process/*">
        <!-- only copy if not "xy" -->
        <xsl:if test="pcode!='xy'">
            <!-- number of preceding elements which are also not "xy" -->
            <xsl:element name="elem{count(preceding-sibling::*[pcode!='xy'])}">
                <xsl:apply-templates select="@*|node()"/>
            </xsl:element>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

とはいえ、これはひどい XML 形式であり、可能であればこの形式を変更して、 のような不明な要素名が含まれないようにする必要がありますelem0。リスト内の要素の位置を知る必要がある場合はposition()count(preceding-sibling::*)、 などを使用して簡単に取得できます。明示的な番号が本当に必要な場合は、要素名ではなく属性に入れます<elem num="1">

于 2013-03-12T16:46:15.880 に答える
0

2 パスの XSLT パターンを使用し、2 番目のパスですべての要素の名前を変更する必要がある場合があります。

<xsl:template match="/">
    <xsl:variable name="pass1">
      <xsl:apply-templates select="Process"/>
    </xsl:variable>
    <xsl:apply-templates select="exsl:node-set($pass1)" mode="pass2" />
<xsl:template>

<xsl:template match="Process" mode="pass2">
  <xsl:copy>
    <xsl:for-each select="*">
       <xsl:element name="{ concat('elem', position()) }">
          <xsl:apply-templates />
       </xsl:element>
    </xsl:for-each>
  </xsl:copy>
</xsl:template>

node-set()XSLT 1 の場合、ほとんどの XSLT 1 プロセッサに含まれている関数を使用する必要がありますが、スタイルシートの先頭に名前空間宣言を含める必要があることに注意してください。ESLT 対応プロセッサ (Saxon、xsltproc、Xalan-J、jd.xslt、および 4XSLT) の場合は、 と を使用xmlns:exsl="http://exslt.org/common"exsl:node-set()ます。Xalan-C の使用xmlns:xalan="http://xml.apache.org/xalan"およびxalan:nodeset(). MSXSL 用xmlns:msxsl="urn:schemas-microsoft-com:xslt"およびmsxsl:node-set().

于 2013-03-12T16:34:56.960 に答える