2

私は他の誰かのためにこれを解決しようとしていますが、自分で問題に遭遇しました。

私はXMLを持っています:

<Process>
  <name>Pro1</name>
  <duration>Dur1</duration>
  <time>Time1</time>
  <name>Pro2</name>
  <duration>Dur2</duration>
  <time>Time2</time>
  <name>Pro3</name>
  <duration>Dur3</duration>
  <time>Time3</time>
  <name>Pro4</name>
  <duration>Dur4</duration>
  <time>Time4</time>
  <name>Pro5</name>
  <duration>Dur5</duration>
  <time>Time5</time>
</Process>

出力:

<Process>
  <Process_Info>
    <name>Pro1</name>
    <duration>Dur1</duration>
    <time>Time1</time>
  </Process_Info>
  <Process_Info>
    <name>Pro2</name>
    <duration>Dur2</duration>
    <time>Time2</time>
  </Process_Info>
  <Process_Info>
    <name>Pro3</name>
    <duration>Dur3</duration>
    <time>Time3</time>
  </Process_Info>
  <Process_Info>
    <name>Pro4</name>
    <duration>Dur4</duration>
    <time>Time4</time>
  </Process_Info>
  <Process_Info>
    <name>Pro5</name>
    <duration>Dur5</duration>
    <time>Time5</time>
  </Process_Info>
</Process>

XSLT の使用:

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

  <xsl:variable name ="varProcess" select ="Process"/>

  <xsl:template match="Process">
    <xsl:element name="Process">
      <xsl:for-each select ="name">
        <xsl:variable name ="posName" select ="position()"/>
        <xsl:element name ="Process_Info">
          <xsl:copy-of select ="."/>
          <xsl:copy-of select="$varProcess/duration[$posName]"/>
          <xsl:copy-of select="$varProcess/time[$posName]"/>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

ただし、<duration>および<time>ノードが常に存在するとは限ら<name>ず、保証されるノードは だけです。したがって、いずれかが欠落している場合、position()選択は失敗します。

<duration>and/or<time>が存在しない場合でも XSLT が機能するように変更するにはどうすればよいですか。

私の理論では、現在の名前ノードの下にある 2 つのノードを選択し、それらがコピーされている<duration>か、またはコピーされているかということです。<time>しかし、それがどのように実装されるかはわかりません。

問題を引き起こす電流出力の例。

入力:

<Process>
  <name>Pro1</name>
  <duration>Dur1</duration>
  <time>Time1</time>
  <name>Pro2</name>
  <duration>Dur2</duration>
  <time>Time2</time>
  <name>Pro3</name>
  <duration>Dur3</duration>
  <time>Time3</time>
  <name>Pro4</name>
  <time>Time4</time>
  <name>Pro5</name>
  <duration>Dur5</duration>
</Process>

出力:

<Process>
  <Process_Info>
    <name>Pro1</name>
    <duration>Dur1</duration>
    <time>Time1</time>
  </Process_Info>
  <Process_Info>
    <name>Pro2</name>
    <duration>Dur2</duration>
    <time>Time2</time>
  </Process_Info>
  <Process_Info>
    <name>Pro3</name>
    <duration>Dur3</duration>
    <time>Time3</time>
  </Process_Info>
  <Process_Info>
    <name>Pro4</name>
    <duration>Dur5</duration> <!-- Should be in the below process_info -->
    <time>Time4</time>
  </Process_Info>
  <Process_Info>
    <name>Pro5</name>
  </Process_Info>
</Process>
4

3 に答える 3

2

アプローチは少し「手動」ですが、これでうまくいきます。これを達成するためのよりエレガントな方法があるかもしれません

<xsl:template match="Process">
    <xsl:element name="Process">
        <xsl:for-each select ="name">
            <xsl:element name ="Process_Info">
                <xsl:copy-of select ="."/>
                <xsl:variable name="firstSib" select="local-name(following-sibling::*[1])" />
                <xsl:variable name="secondSib" select="local-name(following-sibling::*[2])" />
                <xsl:choose>
                    <xsl:when test="$firstSib='duration'">
                        <xsl:copy-of select="following-sibling::*[1]"/>
                        <xsl:choose>
                            <xsl:when test="$secondSib='time'">
                                <xsl:copy-of select="following-sibling::*[2]"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <time>SomeDefaultValueForMissingTime</time>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:when>
                    <xsl:when test="$firstSib='time'">
                        <duration>SomeDefaultValueForMissingDuration</duration>
                        <xsl:copy-of select="following-sibling::*[1]"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <duration>SomeDefaultValueForMissingDuration</duration>
                        <time>SomeDefaultValueForMissingTime</time>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:element>
        </xsl:for-each>
    </xsl:element>
</xsl:template>

入力:

<Process>
    <name>Pro1</name>
    <duration>Dur1</duration>
    <time>Time1</time>
    <name>NameMissingDuration</name>
    <time>TimeMissingDuration</time>
    <name>NameMissingTime</name>
    <duration>DurMissingTime</duration>
    <name>NameMissingBoth</name>
    <name>NormalName</name>
    <duration>NormalDuration</duration>
    <time>NormalTime</time>
</Process>

出力

<Process>
  <Process_Info>
    <name>Pro1</name>
    <duration>Dur1</duration>
    <time>Time1</time>
  </Process_Info>
  <Process_Info>
    <name>NameMissingDuration</name>
    <duration>SomeDefaultValueForMissingDuration</duration>
    <time>TimeMissingDuration</time>
  </Process_Info>
  <Process_Info>
    <name>NameMissingTime</name>
    <duration>DurMissingTime</duration>
    <time>SomeDefaultValueForMissingTime</time>
  </Process_Info>
  <Process_Info>
    <name>NameMissingBoth</name>
    <duration>SomeDefaultValueForMissingDuration</duration>
    <time>SomeDefaultValueForMissingTime</time>
  </Process_Info>
  <Process_Info>
    <name>NormalName</name>
    <duration>NormalDuration</duration>
    <time>NormalTime</time>
  </Process_Info>
</Process>
于 2012-07-18T08:42:07.010 に答える
2

を使用しない代替ソリューションを次に示しxsl:ifます。

これは、現在のname要素に続き、最初の前のname要素が現在の要素である最初の時間(またはduration ) 要素をgenerate-id()選択する際に、ノードの等価性をテストするための関数の使用を示しています。

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

  <xsl:template match="Process">
    <xsl:copy>
      <xsl:apply-templates select="name"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="name">
    <xsl:variable name="this" select="generate-id()"/>
    <Process_Info>
      <xsl:copy-of select="."/>
      <xsl:copy-of select="following-sibling::duration
                           [generate-id(preceding-sibling::name[1]) = $this]
                           [1]"/>
      <xsl:copy-of select="following-sibling::time
                           [generate-id(preceding-sibling::name[1]) = $this]
                           [1]"/>
    </Process_Info>
  </xsl:template>

</xsl:stylesheet>
于 2012-07-18T11:26:10.067 に答える
1

nonnb の応答に基づいているため、すべての功績は彼にあり、最終的な XSLT が使用されています。フィラーノードが必要ないという質問に含めなかった私の間違い。

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

  <xsl:template match="Process">
    <xsl:element name="Process">
      <xsl:for-each select ="name">
        <xsl:element name ="Process_Info">
          <xsl:copy-of select ="."/>
          <xsl:variable name="firstSib" select="local-name(following-sibling::*[1])" />
          <xsl:variable name="secondSib" select="local-name(following-sibling::*[2])" />
          <xsl:if test ="($firstSib='duration') or ($firstSib='time')">
            <xsl:copy-of select="following-sibling::*[1]"/>
          </xsl:if>
          <xsl:if test ="($secondSib='duration') or ($secondSib='time')">
            <xsl:copy-of select="following-sibling::*[2]"/>
          </xsl:if>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
于 2012-07-18T09:47:43.640 に答える