0

私はまだ XSLT に慣れていませんし、XSLT テンプレートにも問題があります。XML データの各インデント レベルに一致するテンプレートを作成しようとしていますが、何らかの理由で、apply-templates 呼び出しのバリエーションに関係なく、最初のインデント レベルしか出力できません。 . というか、1 つのインデント レベルだけを適用しているかのように、最初に出現するパターンに一致し、残りは無視します。私の XSLT 構文について何か問題があるかどうか誰かが教えてくれますか? これと同じ方法が他のデータにも使用され、うまくいきました。

<?xml version="1.0" encoding="ISO-8859-1"?>

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

    <xsl:template match="/">
        <config>
            <xsl:apply-templates match="/Objects/*/*" /> <!-- Matches template #1 -->
            <xsl:apply-templates match="/Objects/*/*/*" /> <!-- Matches template #2 -->
            <xsl:apply-templates match="/Objects/*/*/*/*" /> <!-- Matches template #3 -->
            <xsl:apply-templates match="/Objects/*/*/*/*/*" /> <!-- Matches template #4 -->
            <xsl:apply-templates match="/Objects/*/*/*/*/*/*" /> <!-- Matches template #5 -->
            <xsl:apply-templates match="/Objects/*/*/*/*/*/*/*" /> <!-- Matches template #6 -->
        </config>
    </xsl:template>

    <!-- <xsl:template match="Object">
        <element>
            <typefield>Object</typefield>
            <xsl:call-template name="elementPrinter" />
        </element>
    </xsl:template> -->

    <!-- Begin Template #1 -->
    <xsl:template match="Object/*">
        <element>
            <typefield>
                <xsl:value-of select="@Name" />
            </typefield>
            <xsl:call-template name="elementPrinter" />
        </element>
    </xsl:template>
    <!-- End Template #1 -->

    <!-- Begin Template #2 -->
    <xsl:template match="Object/*/*">
        <element2>
            <typefield>
                <xsl:value-of select="@Name" />
            </typefield>
            <xsl:call-template name="parentIDPrinter" />
            <xsl:call-template name="elementPrinter" />
        </element2>
    </xsl:template>
    <!-- End Template #2 -->

    <!-- Begin Template #3 -->
    <xsl:template match="Object/*/*/*">
        <element>
            <typefield>
                <xsl:value-of select="@Name" />
            </typefield>
            <xsl:call-template name="gparentIDPrinter" />
            <xsl:call-template name="parentIDPrinter" />
            <xsl:call-template name="elementPrinter" />
        </element>
    </xsl:template>
    <!-- End Template #3 -->

    <!-- Begin Template #4 -->
    <xsl:template match="Object/*/*/*/*">
        <element>
            <typefield>
                <xsl:value-of select="@Name" />
            </typefield>
            <xsl:call-template name="gparentIDPrinter" />
            <xsl:call-template name="parentIDPrinter" />
            <xsl:call-template name="elementPrinter" />
        </element>
    </xsl:template>
    <!-- End Template #4 -->

    <!-- Begin Template #5 -->
    <xsl:template match="Object/*/*/*/*/*">
        <element>
            <typefield>
                <xsl:value-of select="@Name" />
            </typefield>
            <xsl:call-template name="gparentIDPrinter" />
            <xsl:call-template name="parentIDPrinter" />
            <xsl:call-template name="elementPrinter" />
        </element>
    </xsl:template>
    <!-- End Template #5 -->

    <!-- Begin Template #6 -->
    <xsl:template match="Object/*/*/*/*/*/*">
        <element>
            <typefield>
                <xsl:value-of select="@Name" />
            </typefield>
            <xsl:call-template name="gparentIDPrinter" />
            <xsl:call-template name="parentIDPrinter" />
            <xsl:call-template name="elementPrinter" />
        </element>
    </xsl:template>
    <!-- End Template #6 -->

    <!-- Prints all elements within the matching node. -->
    <xsl:template name="elementPrinter">
        <xsl:for-each select="*">
            <xsl:if test="text() != ''">
                <xsl:choose>
                    <xsl:when test="@Name">
                        <xsl:variable name="eName">
                            <xsl:value-of select="@Name" />
                        </xsl:variable>

                        <xsl:element name="{$eName}">
                            <xsl:value-of select="text()" />
                        </xsl:element>
                    </xsl:when>
                    <xsl:when test="not(@Name)">
                        <xsl:variable name="eName">
                            <xsl:value-of select="@Type" />
                        </xsl:variable>

                        <xsl:element name="{$eName}">
                            <xsl:value-of select="text()" />
                        </xsl:element>
                    </xsl:when>
                </xsl:choose>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

    <!-- Prints a tag containing the name of the node's parent. -->
    <xsl:template name="parentIDPrinter">
        <xsl:for-each select="../../*[1]">
            <xsl:choose>
                <xsl:when test="./@Name">
                    <xsl:variable name="pName">
                        <xsl:value-of select="@Name" />
                    </xsl:variable>

                    <xsl:element name="parent">
                        <xsl:value-of select="$pName" />
                    </xsl:element>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="pName">
                        <xsl:value-of select="@Type" />
                    </xsl:variable>

                    <xsl:element name="parent">
                        <xsl:value-of select="$pName" />
                    </xsl:element>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>

    <!-- Prints a tag containing the name of the node's grandparent. -->
    <xsl:template name="gparentIDPrinter">
        <xsl:for-each select="../../../../*[1]">
            <xsl:choose>
                <xsl:when test="./@Name">
                    <xsl:variable name="pName">
                        <xsl:value-of select="@Name" />
                    </xsl:variable>

                    <xsl:element name="grandparent">
                        <xsl:value-of select="$pName" />
                    </xsl:element>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="pName">
                        <xsl:value-of select="@Type" />
                    </xsl:variable>

                    <xsl:element name="grandparent">
                        <xsl:value-of select="$pName" />
                    </xsl:element>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

残念ながらサンプルデータは掲載できませんが、フォーマットはほぼこれだけです。

<Objects>
    <Object>
        <Property Name="whatever">
            <Property Name="whatever1.1">whatever</Property>
            <Property Name="whatever1.2">whatever2</Property>
        </Property>
        <Property Name="whatever">
            <Property Name="whatever1.1">whatever</Property>
            <Property Name="whatever1.2">whatever2</Property>
        </Property>
    </Object>
    <Object>
        <Property Name="whatever">
            <Property Name="whatever1.1">whatever</Property>
            <Property Name="whatever1.2">whatever2</Property>
        </Property>
        <Property Name="whatever">
            <Property Name="whatever1.1">whatever</Property>
            <Property Name="whatever1.2">whatever2</Property>
        </Property>
    </Object>
</Objects>

最初の apply-templates 呼び出しだけを残すと、最初のレイヤーが表示されます。これは、すべての最初のレイヤーの Property タグです...しかし、次の行を入れると、テンプレートに一致する必要があります # 2 では、テンプレート 2 のパターン データと一致する代わりに、テンプレート 1 のパターンの直後にまったく同じデータを印刷するだけです。他のテンプレートが無視されるのはなぜですか?

4

1 に答える 1

2

XSLT が無効です -属性ではなく、apply-templates属性があります。それが修正されると、次の結果が生成されます。selectmatch

<config>
  <element>
    <typefield>whatever</typefield>
    <whatever1.1>whatever</whatever1.1>
    <whatever1.2>whatever2</whatever1.2>
  </element>
  <element>
    <typefield>whatever</typefield>
    <whatever1.1>whatever</whatever1.1>
    <whatever1.2>whatever2</whatever1.2>
  </element>
  <element>
    <typefield>whatever</typefield>
    <whatever1.1>whatever</whatever1.1>
    <whatever1.2>whatever2</whatever1.2>
  </element>
  <element>
    <typefield>whatever</typefield>
    <whatever1.1>whatever</whatever1.1>
    <whatever1.2>whatever2</whatever1.2>
  </element>
  <element2>
    <typefield>whatever1.1</typefield>
    <parent>whatever</parent>
  </element2>
  <element2>
    <typefield>whatever1.2</typefield>
    <parent>whatever</parent>
  </element2>
  <element2>
    <typefield>whatever1.1</typefield>
    <parent>whatever</parent>
  </element2>
  <element2>
    <typefield>whatever1.2</typefield>
    <parent>whatever</parent>
  </element2>
  <element2>
    <typefield>whatever1.1</typefield>
    <parent>whatever</parent>
  </element2>
  <element2>
    <typefield>whatever1.2</typefield>
    <parent>whatever</parent>
  </element2>
  <element2>
    <typefield>whatever1.1</typefield>
    <parent>whatever</parent>
  </element2>
  <element2>
    <typefield>whatever1.2</typefield>
    <parent>whatever</parent>
  </element2>
</config>

ここでわかるように、2 番目のテンプレート使用されています。の 8 つのインスタンスがあります<element2><element>すべてのs の後に発生するため、おそらく気付かなかったでしょう。すべてが最初に表示される理由は<elements>、最初にすべての第 1 レベル<Property>ノードにテンプレートを適用してから、次のレベルにテンプレートを適用するためです。各ノードの子を親の後にリストする場合は、次のように XSLT を記述します。

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

  <xsl:template match="/">
    <config>
      <xsl:apply-templates select="/Objects/*/*" />
      <!-- Matches template #1 -->
    </config>
  </xsl:template>

  <!-- <xsl:template match="Object">
        <element>
            <typefield>Object</typefield>
            <xsl:call-template name="elementPrinter" />
        </element>
    </xsl:template> -->

  <!-- Begin Template #1 -->
  <xsl:template match="Object/*">
    <element>
      <typefield>
        <xsl:value-of select="@Name" />
      </typefield>
      <xsl:call-template name="elementPrinter" />
    </element>
    <xsl:apply-templates select="*" />
  </xsl:template>
  <!-- End Template #1 -->

  <!-- Begin Template #2 -->
  <xsl:template match="Object/*/*">
    <element2>
      <typefield>
        <xsl:value-of select="@Name" />
      </typefield>
      <xsl:call-template name="parentIDPrinter" />
      <xsl:call-template name="elementPrinter" />
    </element2>
    <xsl:apply-templates select="*" />
  </xsl:template>
  <!-- End Template #2 -->

  <!-- Begin Template #3 -->
  <xsl:template match="Object/*/*/*">
    <element>
      <typefield>
        <xsl:value-of select="@Name" />
      </typefield>
      <xsl:call-template name="gparentIDPrinter" />
      <xsl:call-template name="parentIDPrinter" />
      <xsl:call-template name="elementPrinter" />
    </element>
    <xsl:apply-templates select="*" />
  </xsl:template>
  <!-- End Template #3 -->

  <!-- Begin Template #4 -->
  <xsl:template match="Object/*/*/*/*">
    <element>
      <typefield>
        <xsl:value-of select="@Name" />
      </typefield>
      <xsl:call-template name="gparentIDPrinter" />
      <xsl:call-template name="parentIDPrinter" />
      <xsl:call-template name="elementPrinter" />
    </element>
    <xsl:apply-templates select="*" />
  </xsl:template>
  <!-- End Template #4 -->

  <!-- Begin Template #5 -->
  <xsl:template match="Object/*/*/*/*/*">
    <element>
      <typefield>
        <xsl:value-of select="@Name" />
      </typefield>
      <xsl:call-template name="gparentIDPrinter" />
      <xsl:call-template name="parentIDPrinter" />
      <xsl:call-template name="elementPrinter" />
    </element>
    <xsl:apply-templates select="*" />
  </xsl:template>
  <!-- End Template #5 -->

  <!-- Begin Template #6 -->
  <xsl:template match="Object/*/*/*/*/*/*">
    <element>
      <typefield>
        <xsl:value-of select="@Name" />
      </typefield>
      <xsl:call-template name="gparentIDPrinter" />
      <xsl:call-template name="parentIDPrinter" />
      <xsl:call-template name="elementPrinter" />
    </element>
    <xsl:apply-templates select="*" />
  </xsl:template>
  <!-- End Template #6 -->

  <!-- Prints all elements within the matching node. -->
  <xsl:template name="elementPrinter">
    <xsl:for-each select="*">
      <xsl:if test="text() != ''">
        <xsl:choose>
          <xsl:when test="@Name">
            <xsl:variable name="eName">
              <xsl:value-of select="@Name" />
            </xsl:variable>

            <xsl:element name="{$eName}">
              <xsl:value-of select="text()" />
            </xsl:element>
          </xsl:when>
          <xsl:when test="not(@Name)">
            <xsl:variable name="eName">
              <xsl:value-of select="@Type" />
            </xsl:variable>

            <xsl:element name="{$eName}">
              <xsl:value-of select="text()" />
            </xsl:element>
          </xsl:when>
        </xsl:choose>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <!-- Prints a tag containing the name of the node's parent. -->
  <xsl:template name="parentIDPrinter">
    <xsl:for-each select="../../*[1]">
      <xsl:choose>
        <xsl:when test="./@Name">
          <xsl:variable name="pName">
            <xsl:value-of select="@Name" />
          </xsl:variable>

          <xsl:element name="parent">
            <xsl:value-of select="$pName" />
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:variable name="pName">
            <xsl:value-of select="@Type" />
          </xsl:variable>

          <xsl:element name="parent">
            <xsl:value-of select="$pName" />
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>

  <!-- Prints a tag containing the name of the node's grandparent. -->
  <xsl:template name="gparentIDPrinter">
    <xsl:for-each select="../../../../*[1]">
      <xsl:choose>
        <xsl:when test="./@Name">
          <xsl:variable name="pName">
            <xsl:value-of select="@Name" />
          </xsl:variable>

          <xsl:element name="grandparent">
            <xsl:value-of select="$pName" />
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:variable name="pName">
            <xsl:value-of select="@Type" />
          </xsl:variable>

          <xsl:element name="grandparent">
            <xsl:value-of select="$pName" />
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

<xsl:apply-templates select="*" />6 つのテンプレートの最後にを追加したことに注目してください。このXSLTを改善する方法は他にもあると思いますが、サンプルに過ぎないようなので、別の質問に譲ります。

あなたの論理もここで壊れていると思います:

<xsl:for-each select="../../*[1]">

そしてここ:

<xsl:for-each select="../../../../*[1]">

親と祖父母のコンテキストに切り替えたい場合は、次を使用する必要があります。

<xsl:for-each select="..">

<xsl:for-each select="../..">
于 2013-02-11T18:54:32.993 に答える