首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根据某些条件,使用XSLT1.0将XML元素按顺序分组到桶中

根据某些条件,使用XSLT1.0将XML元素按顺序分组到桶中
EN

Stack Overflow用户
提问于 2011-06-23 00:36:52
回答 3查看 372关注 0票数 3

假设我有一些XML想要转换成HTML。XML被划分为有序的部分:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<root>
  <section attr="someCriteria">
    <h1>Title 1</h1>
    <p>paragraph 1-1</p>
    <p>paragraph 1-2</p>
  </section>
  <section attr="someOtherCriteria">
    <h3>Subtitle 2</h3>
    <ul>
      <li>list item 2-1</li>
      <li>list item 2-2</li>
      <li>list item 2-3</li>
      <li>list item 2-4</li>
    </ul>
  </section>
  <section attr="anotherSetOfCriteria">
    <warning>
      Warning: This product could kill you
    </warning>
  </section>
  <section attr="evenMoreCriteria">
    <disclaimer>
      You were warned
    </disclaimer>
  </section>
  <section attr="criteriaSupreme">
    <p>Copyright 1999-2011</p>
  </section>
</root>

我有几个这些XML文档。我需要根据标准对这些部分进行分组和转换。会有两种不同的水桶。

  • 因此,第一部分将进入一个桶(例如<div class="FormatOne"></div>)。
  • 如果第二部分符合"FormatOne“桶的条件,那么它也将进入这个桶中。
  • 如果第三节需要一个不同的桶(例如<div class="FormatTwo"></div>),则创建一个新的桶,并将节内容放置在这个桶中。
  • 如果第四节的桶需要"FormatOne“(与以前的格式不同),那么将再次创建一个新的桶,并将节内容放在这个桶中。
  • 等。如果每个部分是相同的格式,它们将进入与前一节相同的桶中。否则,将创建一个新的桶。

因此,对于每个文档,根据分离桶的逻辑,文档可能会以如下方式结束:

代码语言:javascript
复制
<body>
  <div class="FormatOne">
    <h1>Title 1</h1>
    <p>paragraph 1-1</p>
    <p>paragraph 1-2</p>
    <h3>Subtitle 2</h3>
    <ul>
      <li>list item 2-1</li>
      <li>list item 2-2</li>
      <li>list item 2-3</li>
      <li>list item 2-4</li>
    </ul>
  </div>
  <div class="FormatTwo">
    <span class="warningText">
      Warning: This product could kill you
    </span>
  </div>
  <div class="FormatOne">
    <span class="disclaimerText"> You were warned</span>
    <p class="copyright">Copyright 1999-2011</p>
  </div>
</body>

这是:

代码语言:javascript
复制
<body>
  <div class="FormatOne">
    <h1>Title 1</h1>
    <p>paragraph 1-1</p>
    <p>paragraph 1-2</p>
    <h3>Subtitle 2</h3>
  </div>
  <div class="FormatTwo">
    <ul>
      <li>list item 2-1</li>
      <li>list item 2-2</li>
      <li>list item 2-3</li>
      <li>list item 2-4</li>
    </ul>
  </div>
  <div class="FormatOne">
    <span class="warningText">
      Warning: This product could kill you
    </span>
    <span class="disclaimerText"> You were warned</span>
    <p class="copyright">Copyright 1999-2011</p>
  </div>
</body>

甚至这个:

代码语言:javascript
复制
<body>
  <div class="FormatOne">
    <h1>Title 1</h1>
    <p>paragraph 1-1</p>
    <p>paragraph 1-2</p>
    <h3>Subtitle 2</h3>
    <ul>
      <li>list item 2-1</li>
      <li>list item 2-2</li>
      <li>list item 2-3</li>
      <li>list item 2-4</li>
    </ul>
    <span class="warningText">
      Warning: This product could kill you
    </span>
    <span class="disclaimerText"> You were warned</span>
    <p class="copyright">Copyright 1999-2011</p>
  </div>
</body>

取决于如何定义节。

有没有一种方法可以使用XSLT来执行这种分组魔术?

任何帮助都会很好。谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-06-23 01:46:45

我想出了一个解决方案,这个解决方案包括按顺序对每个部分进行访问。每个部分的处理分为两个部分:“外壳”部分和“内容”部分。"shell“负责呈现<div class="FormatOne">...</div>位,而”内容“负责呈现当前节和所有以下部分的实际内容,直到找到不匹配的为止。

当找到一个不匹配的部分时,控件将返回到该部分的"shell“模板。

这提供了一些有趣的灵活性:"shell“模板在它们匹配的内容上可能非常具有攻击性,而”内容“部分可能更有洞察力。具体来说,对于第一个示例输出,需要warning元素显示为<span class="warningText">...</span>,这是通过一个更紧密匹配的模板完成的。

在呈现当前部分的内容之后,所有" content“模板都调用一个命名模板,该模板查找"next”适当的内容部分。这有助于巩固规则,以确定什么是“匹配”部分。

您可以在这里看到一个有用的示例。

下面是我的代码,用于复制您在第一个示例中要求的内容:

代码语言:javascript
复制
<?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" />

    <xsl:template match="/">
        <body>
            <xsl:apply-templates select="/root/section[1]" mode="shell" />
        </body>
    </xsl:template>

    <xsl:template match="section[
        @attr = 'someCriteria' or
        @attr = 'someOtherCriteria' or
        @attr = 'evenMoreCriteria' or
        @attr = 'criteriaSupreme']" mode="shell">

        <div class="FormatOne">
            <xsl:apply-templates select="." mode="contents" />
        </div>

        <xsl:apply-templates select="following-sibling::section[
            @attr != 'someCritera' and
            @attr != 'someOtherCriteria' and
            @attr != 'evenMoreCriteria' and
            @attr != 'criteriaSupreme'][1]" mode="shell" />

    </xsl:template>

    <xsl:template name="nextFormatOne">
        <xsl:variable name="next" select="following-sibling::section[1]" />
        <xsl:if test="$next[
            @attr = 'someCriteria' or
            @attr = 'someOtherCriteria' or
            @attr = 'evenMoreCriteria' or
            @attr = 'criteriaSupreme']">
            <xsl:apply-templates select="$next" mode="contents" />
        </xsl:if>
    </xsl:template>

    <xsl:template match="section[
        @attr = 'someCriteria' or
        @attr = 'someOtherCriteria']" mode="contents">

        <xsl:copy-of select="*" />

        <xsl:call-template name="nextFormatOne" />
    </xsl:template>

    <xsl:template match="section[@attr = 'evenMoreCriteria']" mode="contents">
        <span class="disclaimerText">
            <xsl:value-of select="disclaimer" />
        </span>

        <xsl:call-template name="nextFormatOne" />
    </xsl:template>

    <xsl:template match="section[@attr = 'criteriaSupreme']" mode="contents">
        <p class="copyright">
            <xsl:value-of select="p" />
        </p>

        <xsl:call-template name="nextFormatOne" />
    </xsl:template>

    <xsl:template match="section[@attr = 'anotherSetOfCriteria']" mode="shell">
        <div class="FormatTwo">
            <xsl:apply-templates select="." mode="contents" />
        </div>
        <xsl:apply-templates select="
            following-sibling::section[@attr != 'anotherSetOfCriteria'][1]"
            mode="shell" />
    </xsl:template>

    <xsl:template name="nextFormatTwo">
        <xsl:variable name="next" select="following-sibling::section[1]" />
        <xsl:if test="$next[@attr = 'anotherSetOfCriteria']">
            <xsl:apply-templates select="$next" mode="contents" />
        </xsl:if>
    </xsl:template>

    <xsl:template
        match="section[@attr = 'anotherSetOfCriteria']"
        mode="contents">

        <span class="warningText">
            <xsl:value-of select="warning" />
        </span>

        <xsl:call-template name="nextFormatTwo" />
    </xsl:template>

</xsl:stylesheet>
票数 3
EN

Stack Overflow用户

发布于 2011-06-23 09:07:13

“如果每个区段的格式相同,它们将进入与前一节相同的桶中。否则,将创建一个新的桶。”

您所描述的实质上是指令所执行的任务。

代码语言:javascript
复制
<xsl:for-each-group group-adjacent="....">

在XSLT2.0中。这假设您可以编写一个将“条件”转换为桶名的函数,并在组相邻属性中调用该函数。

那么,您需要使用XSLT1.0的约束有多大?

如果您只使用1.0,那么您就必须按照Chris的建议,使用同级递归设计模式。

票数 1
EN

Stack Overflow用户

发布于 2011-06-23 00:51:34

看看templateifchoosefor-each

  • templates.asp
  • if.asp
  • choose.asp
  • each.asp

这些(以及其他XSLT功能)将允许您进行条件行为,以便在不同的转换逻辑之间切换。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6448139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档