将一个 XML XSLT 转为 HTML 生成两列

发布于 2024-11-01 03:53:26 字数 3227 浏览 0 评论 0原文

我有来自无法更改的源的 XML。他们将其作为列表发送,但列表也可以嵌入列表。这是一个简短的例子:

<LinkList>
  <ListHeader>A</ListHeader>
  <ArticleLink chunkiid="13121">A Test 1</ArticleLink>
  <ArticleLink chunkiid="13122">A Test 2</ArticleLink>
  <ArticleLink chunkiid="13123">A Test 3</ArticleLink>
  <LinkList>
    <ListHeader>
      <ArticleLink chunkiid="13124">A Inner List</ArticleLink>
    </ListHeader>
    <ArticleLink chunkiid="13125">A Inner Test 1</ArticleLink>
    <ArticleLink chunkiid="13126">A Inner Test 2</ArticleLink>
  </LinkList>
  <ArticleLink chunkiid="13127">A Test 4</ArticleLink>
  <ArticleLink chunkiid="13128">A Test 5</ArticleLink>
</LinkList>

请记住,它在现实生活中要大得多。我想使用 XSLT 或 CSS 或 JQuery 将其分成两列。如果我将其保留为一列,则当前输出如下所示:

<b>A</b>
<ul>
    <li><a href="Article.aspx?id=13121">A Test 1</a></li>
    <li><a href="Article.aspx?id=13122">A Test 2</a></li>
    <li><a href="Article.aspx?id=13123">A Test 3</a></li>
    <li>
        <b><a href="Article.aspx?id=13124">A Inner List</a></b>
        <ul>
            <li><a href="Article.aspx?id=13125">A Inner Test 1</a></li>
            <li><a href="Article.aspx?id=13126">A Inner Test 1</a></li>
        </ul>
    </li>
    <li><a href="Article.aspx?id=13127">A Test 4</a></li>
    <li><a href="Article.aspx?id=13128">A Test 5</a></li>
</ul>

我已经能够使用 XSLT 将其拆分,但我只能在底部列表上进行拆分,因此如果存在内部列表,有时会使一侧或另一侧更长。我正在对一个变量进行计数,然后在 XSLT 中应用这样的模板:

<xsl:template match="LinkList">
  <xsl:if test="ListHeader = $CurrentAlphaIndex">
    <xsl:apply-templates select="@*"/>
    <xsl:apply-templates select="ListHeader"/>
    <xsl:variable name="OneSideCount">
      <xsl:value-of select="ceiling((count(child::*) - 1) div 2)" />
    </xsl:variable>
    <div class="col-50">
      <div class="layout-inner-2">
        <ul>
          <xsl:apply-templates select="*[not(self::ListHeader) and (position() - 1) &lt;= $OneSideCount]">
            <xsl:sort select="."/>
          </xsl:apply-templates>
        </ul>
      </div>
    </div>
    <div class="col-50">
      <div class="layout-inner-2">
        <ul>
          <xsl:apply-templates select="*[not(self::ListHeader) and (position() - 1) &gt; $OneSideCount]">
            <xsl:sort select="."/>
          </xsl:apply-templates>
        </ul>
      </div>
    </div>
    <div class="spacer">&amp;nbsp;</div>
  </xsl:if>
</xsl:template>

我遗漏了一些模板,因为我不想让它太长。我认为这显示了我现在如何将其分解,但从我的示例中您可以看到由于内部列表,右侧更长。

有什么方法可以将其保留为单个列表并使用 CSS 或 JQuery 将其分成两列吗?如果没有,有没有办法可以对 XML 中的所有链接进行计数,并使用还包含子节点的position() 将其拆分?

更新 我所说的两列是指一半记录在页面的一侧,一半在另一侧。抱歉,XSLT 仅使用 div 标签,因为这是客户及其设计者在该网站上设置的标准。

I have XML coming from a source that I can't change. They send it as a list but the lists can also have embedded lists. Here is an example keeping it short:

<LinkList>
  <ListHeader>A</ListHeader>
  <ArticleLink chunkiid="13121">A Test 1</ArticleLink>
  <ArticleLink chunkiid="13122">A Test 2</ArticleLink>
  <ArticleLink chunkiid="13123">A Test 3</ArticleLink>
  <LinkList>
    <ListHeader>
      <ArticleLink chunkiid="13124">A Inner List</ArticleLink>
    </ListHeader>
    <ArticleLink chunkiid="13125">A Inner Test 1</ArticleLink>
    <ArticleLink chunkiid="13126">A Inner Test 2</ArticleLink>
  </LinkList>
  <ArticleLink chunkiid="13127">A Test 4</ArticleLink>
  <ArticleLink chunkiid="13128">A Test 5</ArticleLink>
</LinkList>

Keep in mind it is much bigger in real life. I want to split this into two columns using XSLT or CSS or JQuery. The current output if I leave it one column looks like this:

<b>A</b>
<ul>
    <li><a href="Article.aspx?id=13121">A Test 1</a></li>
    <li><a href="Article.aspx?id=13122">A Test 2</a></li>
    <li><a href="Article.aspx?id=13123">A Test 3</a></li>
    <li>
        <b><a href="Article.aspx?id=13124">A Inner List</a></b>
        <ul>
            <li><a href="Article.aspx?id=13125">A Inner Test 1</a></li>
            <li><a href="Article.aspx?id=13126">A Inner Test 1</a></li>
        </ul>
    </li>
    <li><a href="Article.aspx?id=13127">A Test 4</a></li>
    <li><a href="Article.aspx?id=13128">A Test 5</a></li>
</ul>

I have been able to split it using XSLT but I can only do it on the bottom list so if there are inner lists it sometimes make one side or the other longer. I am doing a count in to a variable and then applying a template like this in XSLT:

<xsl:template match="LinkList">
  <xsl:if test="ListHeader = $CurrentAlphaIndex">
    <xsl:apply-templates select="@*"/>
    <xsl:apply-templates select="ListHeader"/>
    <xsl:variable name="OneSideCount">
      <xsl:value-of select="ceiling((count(child::*) - 1) div 2)" />
    </xsl:variable>
    <div class="col-50">
      <div class="layout-inner-2">
        <ul>
          <xsl:apply-templates select="*[not(self::ListHeader) and (position() - 1) <= $OneSideCount]">
            <xsl:sort select="."/>
          </xsl:apply-templates>
        </ul>
      </div>
    </div>
    <div class="col-50">
      <div class="layout-inner-2">
        <ul>
          <xsl:apply-templates select="*[not(self::ListHeader) and (position() - 1) > $OneSideCount]">
            <xsl:sort select="."/>
          </xsl:apply-templates>
        </ul>
      </div>
    </div>
    <div class="spacer">&nbsp;</div>
  </xsl:if>
</xsl:template>

I left out some of the templates as I didn't want this to long. I figure this shows how I am breaking it up right now but from my example you can see the right side is longer because of the inner list.

Is there any way to leave it a single list and break it up into two columns using CSS or JQuery? If not is there a way I can count all links in the XML and split it up using a position() that also includes children nodes?

Update
What I mean by two columns is having half the records on one side of the page and half on the other. Sorry the XSLT is using div tags only because that is the standard on this site set by the client and their designer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

狂之美人 2024-11-08 03:53:26

没有扩展功能只是为了好玩:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="CurrentAlphaIndex" select="'A'"/>
    <xsl:param name="pColumns" select="2"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="LinkList">
        <xsl:if test="ListHeader = $CurrentAlphaIndex">
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="ListHeader"/>
            <xsl:variable name="vArticleLinks"
                 select="descendant-or-self::LinkList/ArticleLink"/>
            <xsl:variable name="OneSideCount"
                 select="ceiling(count($vArticleLinks) div $pColumns)"/>
            <xsl:apply-templates
                 select="$vArticleLinks[position() mod $OneSideCount = 1]"
                 mode="partition">
                <xsl:with-param name="OneSideCount"
                                select="$OneSideCount"/>
                <xsl:with-param name="pArticleLinks"
                                select="$vArticleLinks"/>
            </xsl:apply-templates>
            <div class="spacer">&nbsp;</div>
        </xsl:if>
    </xsl:template>
    <xsl:template match="ArticleLink" mode="partition">
        <xsl:param name="pArticleLinks" select="/.."/>
        <xsl:param name="OneSideCount" select="0"/>
        <xsl:variable name="vOffSet"
                      select="(position() - 1) * $OneSideCount"/>
        <div class="col-50">
            <div class="layout-inner-2">
                <ul>
                    <xsl:apply-templates select="$pArticleLinks"
                                         mode="filter">
                        <xsl:with-param name="OneSideCount"
                             select="$OneSideCount"/>
                        <xsl:with-param name="pOffSet"
                             select="(position() - 1) * $OneSideCount"/>
                        <xsl:sort/>
                    </xsl:apply-templates>
                </ul>
            </div>
        </div>
    </xsl:template>
    <xsl:template match="ArticleLink" mode="filter">
        <xsl:param name="pOffSet" select="0"/>
        <xsl:param name="OneSideCount" select="0"/>
        <xsl:if test="position() > $pOffSet
                         and
                      $pOffSet + $OneSideCount >= position()">
            <xsl:apply-templates select="."/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

输出:

<ListHeader>A</ListHeader>
<div class="col-50">
    <div class="layout-inner-2">
        <ul>
            <ArticleLink chunkiid="13125">A Inner Test 1</ArticleLink>
            <ArticleLink chunkiid="13126">A Inner Test 2</ArticleLink>
            <ArticleLink chunkiid="13121">A Test 1</ArticleLink>
            <ArticleLink chunkiid="13122">A Test 2</ArticleLink>
        </ul>
    </div>
</div>
<div class="col-50">
    <div class="layout-inner-2">
        <ul>
            <ArticleLink chunkiid="13123">A Test 3</ArticleLink>
            <ArticleLink chunkiid="13127">A Test 4</ArticleLink>
            <ArticleLink chunkiid="13128">A Test 5</ArticleLink>
        </ul>
    </div>
</div>
<div class="spacer">&nbsp;</div>

有扩展(更好的性能):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl">
    <xsl:param name="CurrentAlphaIndex" select="'A'"/>
    <xsl:param name="pColumns" select="2"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="LinkList">
        <xsl:if test="ListHeader = $CurrentAlphaIndex">
            <xsl:apply-templates select="@*|ListHeader"/>
            <xsl:variable name="vrftArticleLinks">
                <xsl:for-each
                 select="descendant-or-self::LinkList/ArticleLink">
                    <xsl:sort/>
                    <xsl:copy-of select="."/>
                </xsl:for-each>
            </xsl:variable>
            <xsl:variable name="vArticleLinks"
                 select="msxsl:node-set($vrftArticleLinks)/*"/>
            <xsl:variable name="OneSideCount"
                 select="ceiling(count($vArticleLinks) div $pColumns)"/>
            <xsl:for-each
                 select="$vArticleLinks[position() mod $OneSideCount = 1]">
                <div class="col-50">
                    <div class="layout-inner-2">
                        <ul>
                            <xsl:apply-templates
                             select=".|following-sibling::*[
                                          $OneSideCount > position()
                                       ]"/>
                        </ul>
                    </div>
                </div>
            </xsl:for-each>
            <div class="spacer">&nbsp;</div>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Without extension functions just for fun:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="CurrentAlphaIndex" select="'A'"/>
    <xsl:param name="pColumns" select="2"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="LinkList">
        <xsl:if test="ListHeader = $CurrentAlphaIndex">
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="ListHeader"/>
            <xsl:variable name="vArticleLinks"
                 select="descendant-or-self::LinkList/ArticleLink"/>
            <xsl:variable name="OneSideCount"
                 select="ceiling(count($vArticleLinks) div $pColumns)"/>
            <xsl:apply-templates
                 select="$vArticleLinks[position() mod $OneSideCount = 1]"
                 mode="partition">
                <xsl:with-param name="OneSideCount"
                                select="$OneSideCount"/>
                <xsl:with-param name="pArticleLinks"
                                select="$vArticleLinks"/>
            </xsl:apply-templates>
            <div class="spacer">&nbsp;</div>
        </xsl:if>
    </xsl:template>
    <xsl:template match="ArticleLink" mode="partition">
        <xsl:param name="pArticleLinks" select="/.."/>
        <xsl:param name="OneSideCount" select="0"/>
        <xsl:variable name="vOffSet"
                      select="(position() - 1) * $OneSideCount"/>
        <div class="col-50">
            <div class="layout-inner-2">
                <ul>
                    <xsl:apply-templates select="$pArticleLinks"
                                         mode="filter">
                        <xsl:with-param name="OneSideCount"
                             select="$OneSideCount"/>
                        <xsl:with-param name="pOffSet"
                             select="(position() - 1) * $OneSideCount"/>
                        <xsl:sort/>
                    </xsl:apply-templates>
                </ul>
            </div>
        </div>
    </xsl:template>
    <xsl:template match="ArticleLink" mode="filter">
        <xsl:param name="pOffSet" select="0"/>
        <xsl:param name="OneSideCount" select="0"/>
        <xsl:if test="position() > $pOffSet
                         and
                      $pOffSet + $OneSideCount >= position()">
            <xsl:apply-templates select="."/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Output:

<ListHeader>A</ListHeader>
<div class="col-50">
    <div class="layout-inner-2">
        <ul>
            <ArticleLink chunkiid="13125">A Inner Test 1</ArticleLink>
            <ArticleLink chunkiid="13126">A Inner Test 2</ArticleLink>
            <ArticleLink chunkiid="13121">A Test 1</ArticleLink>
            <ArticleLink chunkiid="13122">A Test 2</ArticleLink>
        </ul>
    </div>
</div>
<div class="col-50">
    <div class="layout-inner-2">
        <ul>
            <ArticleLink chunkiid="13123">A Test 3</ArticleLink>
            <ArticleLink chunkiid="13127">A Test 4</ArticleLink>
            <ArticleLink chunkiid="13128">A Test 5</ArticleLink>
        </ul>
    </div>
</div>
<div class="spacer">&nbsp;</div>

With extensions (better performance):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl">
    <xsl:param name="CurrentAlphaIndex" select="'A'"/>
    <xsl:param name="pColumns" select="2"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="LinkList">
        <xsl:if test="ListHeader = $CurrentAlphaIndex">
            <xsl:apply-templates select="@*|ListHeader"/>
            <xsl:variable name="vrftArticleLinks">
                <xsl:for-each
                 select="descendant-or-self::LinkList/ArticleLink">
                    <xsl:sort/>
                    <xsl:copy-of select="."/>
                </xsl:for-each>
            </xsl:variable>
            <xsl:variable name="vArticleLinks"
                 select="msxsl:node-set($vrftArticleLinks)/*"/>
            <xsl:variable name="OneSideCount"
                 select="ceiling(count($vArticleLinks) div $pColumns)"/>
            <xsl:for-each
                 select="$vArticleLinks[position() mod $OneSideCount = 1]">
                <div class="col-50">
                    <div class="layout-inner-2">
                        <ul>
                            <xsl:apply-templates
                             select=".|following-sibling::*[
                                          $OneSideCount > position()
                                       ]"/>
                        </ul>
                    </div>
                </div>
            </xsl:for-each>
            <div class="spacer">&nbsp;</div>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文