2

下面我创建了一个简单的 XML 示例来说明我的 xml 的样子。我有一个包含我想观看的数字的属性。它有点像一个计数器,在转换过程中,每当计数器 ++ 时,我都想添加一些东西。

问题是我的 xml 文件中的级别数。在这里我只做了三个,但实际上我有 8 个甚至更多。我需要找到一种方法将当前节点与前一个节点进行比较(反之亦然),但要考虑级别。因此,例如在下面的示例中,需要将 id 为 4 的 lvl2 节点与 id 为 3 的 lvl3 节点进行比较,以找出 id 属性是否已被提升

xml:

<lvl1 id="1">
    <lvl2 id="1">
        <lvl3 id="1"></lvl3>
        <lvl3 id ="2"></lvl3>
    </lvl2>
    <lvl2 id="2">
        <lvl3 id="3"></lvl3>                        
    </lvl2>
    <lvl2 id="4"></lvl2>
</lvl1>

由于使用 xslt 全局计数器变量是不可能的,所以我目前没有想法,似乎在这里或其他任何地方都找不到。

输出将类似于:

  <ul>
<div>id 1</div>
<li>
  <ul>
    <li>
      <ul>
        <li></li>
        <div>id 2</div>
        <li></li>
      </ul>
    </li>
    <li>
      <ul>
        <div>id 3</div>
        <li></li>
      </ul>
    </li>
    <div>id 4</div>
    <li></li>
  </ul>
</li>

这里将 xml 转换为 html 输出但没有 div 的样式表:

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
    <ul>
            <xsl:value-of select="@id"/>
            <xsl:apply-templates select="lvl1"/>
    </ul>
</xsl:template>
<xsl:template match="lvl1">
    <li class="{@id}">
        lvl 1
        <ul>
            <xsl:apply-templates select="lvl2"/>
        </ul>
    </li>
</xsl:template>
<xsl:template match="lvl2">
    <li class="{@id}">lvl 2
        <ul>
            <xsl:apply-templates select="lvl3"/>
        </ul>
    </li>
</xsl:template>
<xsl:template match="lvl3">
    <li class="{@id}">lvl 3
    </li>
</xsl:template>

4

2 回答 2

0

如果应用此 XSLT

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

    <xsl:template match='/'>
        <ul>
            <xsl:apply-templates select='*' />
        </ul>
    </xsl:template>

    <xsl:template match="*">
        <li>
        <div>
            <xsl:value-of select='@id' />
            <xsl:if test='count(*)&gt;0'>
                <ul>
                    <xsl:apply-templates select='*' />
                </ul>
            </xsl:if>
        </div>
        </li>
    </xsl:template>

    </xsl:stylesheet>

你得到的东西可能是你问的:

    <ul>
      <li>
        <div>1<ul>
            <li>
              <div>1<ul>
                  <li>
                    <div>1</div>
                  </li>
                  <li>
                    <div>2</div>
                  </li>
                </ul>
              </div>
            </li>
            <li>
              <div>2<ul>
                  <li>
                    <div>3</div>
                  </li>
                </ul>
              </div>
            </li>
            <li>
              <div>4</div>
            </li>
          </ul>
        </div>
      </li>
    </ul>
于 2012-08-14T11:39:33.910 回答
0

这个问题比看起来要复杂一些,因为preceding::并不总是在这里找到@id当前元素之前的最后一个。您还需要检查@id父级并考虑根位置。此代码使用问题中给出的 XML 生成所需的结果。看我里面的评论。

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

<xsl:template match="*">
    <!-- get preceding (or parent) id -->
    <xsl:variable name="lastId">
        <xsl:choose>
            <!-- try to get id from first preceding element -->
            <xsl:when test="preceding::*[1]/@id">
                <xsl:value-of select="preceding::*[1]/@id"/>
            </xsl:when>
            <!-- there could still be ids in parent elements -->
            <xsl:when test="../@id">
                <xsl:value-of select="../@id"/>
            </xsl:when>
            <!-- or this is the root element -->
            <xsl:otherwise>
                <xsl:value-of select="0"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <!-- now compare current and last id -->
    <xsl:if test="@id > $lastId">
        <div>
            <xsl:text>id </xsl:text>
            <xsl:value-of select="@id"/>
        </div>
    </xsl:if>
    <!-- create list item -->
    <li>
        <!-- check for subelements -->
        <xsl:if test="*">
            <ul>
                <xsl:apply-templates/>
            </ul>
        </xsl:if>
    </li>
</xsl:template>

根据您的实际情况,您可能希望限制match="*"为,如LarsHmatch="*[starts-with(local-name(),'lvl')]"的评论中所建议的那样。

于 2017-11-22T23:43:11.817 回答