0

まず、私はこの質問を認識しています: XSLT: 一度に 2 つの要素を選択するループ

ただし、要素の構造が原因で機能することがわかりませんでした。または、2 つのうちの 1 つである mod の使用に失敗しました。

<input>
  <node>
    <id>1</id>
    <value>3</value>
  </node>
  <node>
    <id>1</id>
    <value>3</value>
  </node>
  <node>
    <id>1</id>
    <value>3</value>
  </node>
  <node>
    <id>1</id>
    <value>3</value>
  </node>
  <node>
    <id>2</id>
    <value>4</value>
  </node>
  <node>
    <id>2</id>
    <value>4</value>
  </node>
  <node>
    <id>2</id>
    <value>4</value>
  </node>
  <node>
    <id>2</id>
    <value>4</value>
  </node>
</input>

次の構造を持つ XML の次のレイアウトがあります。 - 同じ ID のノードは常にグループ化されます - 1 つの ID に対して常に 4 つのノードがあります。

一度に 1 つの ID の 4 つのノードを選択し、4 つの各グループをループして、データを 1 つの出力行に操作できるようにしたいと考えています。

これにアプローチする最良の方法は何ですか?

4

3 に答える 3

1

node要素は常に4つのグループであることが保証されているため、必要な出力は、グループ化方法(Muenchianや兄弟比較など)を使用せず、おそらくより効率的な非常に単純な変換によって生成できます

<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()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="node">
  <sample>
   <xsl:call-template name="identity"/>
  </sample>
 </xsl:template>
 <xsl:template match="node[not(position() mod 4 = 1)]"/>
</xsl:stylesheet>

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

<input>
  <node>
    <id>1</id>
    <value>3</value>
  </node>
  <node>
    <id>1</id>
    <value>3</value>
  </node>
  <node>
    <id>1</id>
    <value>3</value>
  </node>
  <node>
    <id>1</id>
    <value>3</value>
  </node>
  <node>
    <id>2</id>
    <value>4</value>
  </node>
  <node>
    <id>2</id>
    <value>4</value>
  </node>
  <node>
    <id>2</id>
    <value>4</value>
  </node>
  <node>
    <id>2</id>
    <value>4</value>
  </node>
</input>

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

<input>
   <sample>
      <node>
         <id>1</id>
         <value>3</value>
      </node>
   </sample>
   <sample>
      <node>
         <id>2</id>
         <value>4</value>
      </node>
   </sample>
</input>

説明

  1. IDルールは、実行対象として選択されたすべてのノードを「現状のまま」コピーします。

  2. 別のテンプレートは、その親のst子であるすべてnodeの要素のIDテンプレートをオーバーライドします。このテンプレートはラッパー要素()を生成し、名前でIDテンプレートを呼び出して、それ自体を出力にコピーします。4k+1nodesample

  3. nodeさらに別のテンプレートは、すべての要素のIDテンプレートをオーバーライドします。このテンプレートはすべてのnode要素に一致しますが、実行対象として選択されます(前のテンプレートよりも優先されます)。前のテンプレートと一致しないノード、つまり親のst 子でnodeはない要素に対してのみ選択されます。これは、このテンプレートが前のテンプレートよりも具体的でないためです。4k+1node

  4. 上記の3.で説明したテンプレートには本体がなく、これにより、一致したnode要素が出力から効果的に「削除」されます。

于 2012-08-29T11:53:52.157 に答える
1

この XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:key name="keyByID" match="node" use="id"/>

<xsl:template match="/">
    <output>
        <xsl:apply-templates/>
    </output>
</xsl:template>

<xsl:template match="input">
    <xsl:for-each select="node[generate-id()=generate-id(key('keyByID',id)[1])]">
        <block>
            <id>
                <xsl:value-of select="id"/>
            </id>
            <value>
                <xsl:value-of select="value"/>
            </value>
        </block>
    </xsl:for-each>
</xsl:template>


</xsl:stylesheet>

入力 XML に適用されます。

<?xml version="1.0" encoding="UTF-8"?>
<input>
<node>
    <id>1</id>
    <value>3</value>
</node>
<node>
    <id>1</id>
    <value>3</value>
</node>
<node>
    <id>1</id>
    <value>3</value>
</node>
<node>
    <id>1</id>
    <value>3</value>
</node>
<node>
    <id>2</id>
    <value>4</value>
</node>
<node>
    <id>2</id>
    <value>4</value>
</node>
<node>
    <id>2</id>
    <value>4</value>
</node>
<node>
    <id>2</id>
    <value>4</value>
</node>
</input>

このグループ化された出力 XML を提供します。

<?xml version="1.0" encoding="UTF-8"?>
<output>
<block>
    <id>1</id>
    <value>3</value>
</block>
<block>
    <id>2</id>
    <value>4</value>
</block>
</output>

出力は によってグループ化され<id>ます。それはあなたが探しているものですか?私はわかりません。この Muenchian Grouping は、構造を単純化するだけです。

于 2012-08-29T08:42:49.570 に答える
0

同じIDのノードが常にそのように隣接することを保証できる場合、

<xsl:template match="node[not(preceding-sibling::node[1]/id = id])">

各 ID の最初のノード (技術的には、その前のノードの ID とは異なる ID を持つすべてのノード) に一致し、そのテンプレート内で他のノードfollowing-sibling::を見つけるために使用するか、単に上部にキーを定義することができます。 level を使用して、同じ ID を持つすべてのノードを抽出します。

于 2012-08-29T08:38:45.467 に答える