【问题标题】:Repopulating an HTML table on-the-fly即时重新填充 HTML 表格
【发布时间】:2011-05-16 06:23:31
【问题描述】:

我有一些像这样的简单 XML:

<Tag>
<Keyphrases>
<Keyphrase Phrase = "This is phrase one"/>
<Keyphrase Phrase = "This is phrase two"/>
<Keyphrase Phrase = "This is phrase three"/>
</Keyphrases>
</Tag>

我有一个 XSLT,其中包含:

[...]

<table id="realtimetable">
<xsl:apply-templates select="Tag/Keyphrases"/>
</table>

[...]

<!-- Build KeyPhrase Rows -->
<xsl:template match="Tag/Keyphrases">
<xsl:for-each select="Keyphrase">
<tr><td>
<xsl:value-of select="@Phrase" />
</td></tr>
</xsl:for-each>
</xsl:template>

但现在我希望即时更新该表的内容。我知道我可以使用 XMLHttpRequest() 来获取新数据。

但是,我不知道这些更新使用什么格式或如何将新数据插入到表中。

我可以提供 XML 的更新。但是我可以重新使用现有的 XSLT 模板来解析它并重新填充显示的表格吗?这看起来优雅而整洁,但有可能吗?如果可以,我该怎么做?

如果这不可能,我想我可以编写 Javascript 来解析 XML 并自己更新表格。这听起来像很多繁重的工作:-(

所以我也在考虑以 JSON 格式响应 XMLHTTPRequest。我认为处理 JSON 可能比解析 XML 更容易。

但是我的 JSON 文档应该是什么样子?如何编写 JavaScript 来处理 JSON 并重新填充表格?

假设我有来自 XMLHttpRequest() 的干净(错误检查)响应,我该怎么办?

function ProcessUpdate() 
{
}

我宁愿避免在这个项目中使用任何库,例如 jQuery。

更新:

感谢您的所有回复。一些cmets和澄清:

  1. 此时避免使用 jQuery 等的原因是...... a) 这个项目已经有很多其他依赖项,我正试图限制老鼠巢的增长。 b) 我倾向于用自下而上的方法更有效地学习新东西。当我了解了较低级别的原子操作后,使用高级库为我完成繁重的工作会感觉更自在。

  2. 有问题的表非常小而且简单。因此,我倾向于在每次更新时从头开始重新创建整个表。确实没有必要处理选择性更新的复杂性。

  3. Dimitre:您的 XSL 看起来很吸引人,我一定会花一些时间来消化它。但是,我(根本)不明白的是如何调用此更新。即如何从 JavaScript 触发这种重新转换?

【问题讨论】:

  • 为什么你更喜欢自己写东西而不是使用 jQuery?你有什么反对意见 - 依赖关系、规模、缺乏熟悉度等?
  • 我不明白这个链条。假设一个原始 XML 文档。这将使用您的 XSLT 样式表进行转换,从而生成一个 XHTML 表。现在,新请求的 XML 文档会包含以前和更新的数据还是仅包含更新的数据?
  • 好问题,+1。有关完整且自然的 XSLT 解决方案,请参阅我的答案。 :)

标签: javascript xml json xslt xmlhttprequest


【解决方案1】:

我强烈建议使用 JSON 而不是 XML 来完成这项任务——正如您已经意识到的那样,您可能不想在客户端解析 XML。

将 XHR 响应作为 JSON 数据后,您可以使用客户端模板将响应转换为标记,然后将标记放置在您的页面上。如果您改变了对 jQuery 的看法,那么 jQuery 有一个模板插件 (jQuery.tmpl) 可以用来完成此操作;还有独立的mustache.js,以及极其轻量级的underscore.js。当然,您也可以编写自己的模板代码。所有客户端模板工具都遵循相同的一般原则(尽管语法不同,因此请务必阅读文档),采用以下模板:

<p>Hello, my name is ${firstName} ${lastName}</p>

...然后取一些数据,比如:

{ "firstName" : "Rebecca", "lastName" : "Murphey" }

...然后将它们组合起来以创建所需的输出,然后可以将其添加到您的 DOM 中。

如果您尝试更新现有表格,您可以为整个表格生成 HTML,然后删除旧表格并插入新表格。或者,您可以只追加新行——这取决于您要执行的操作的确切性质。

最后:正如评论者所说,我会重新考虑您反对使用任何类型的库,除非有真正令人信服的理由不这样做。重新发明轮子并不光彩。

【讨论】:

    【解决方案2】:

    如果你愿意,你可以在我的库中看看我是怎么做的,this 函数调用this 处理 JSON 的可爱函数集。而this 函数用于进行 AJAX 调用,我对跨浏览器兼容性进行了很多研究,因此它是一个很好的例子。

    如果您使用的是 PHP,那么您可以将数据编码为 JSON 并将其传递回您的 JS,如下所示:

    echo json_encode($myData);
    

    我认为这并没有解决你的问题,但我认为它确实帮助你更接近了。

    【讨论】:

      【解决方案3】:

      这是一个 XSLT 转换,其更新被接受为外部参数。它作为源 XML 文档对当前表进行操作

      <xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       xmlns:ext="http://exslt.org/common"
       exclude-result-prefixes="ext">
       <xsl:output omit-xml-declaration="yes" indent="yes"/>
       <xsl:strip-space elements="*"/>
      
       <xsl:param name="pReps">
        <updates>
         <replace line="2">This is new phrase two</replace>
         <delete line="3"/>
         <insert-before line="1">This is phrase zero (new)</insert-before>
         <insert-after line="4">This is phrase five (new)</insert-after>
        </updates>
       </xsl:param>
      
       <xsl:variable name="vReps"
            select="ext:node-set($pReps)/*/*"/>
      
       <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
         <xsl:apply-templates select="@*"/>
         <xsl:apply-templates select="node()"/>
        </xsl:copy>
       </xsl:template>
      
       <xsl:template match="tr">
        <xsl:choose>
         <xsl:when test="not(position()=$vReps/@line)">
          <xsl:call-template name="identity"/>
         </xsl:when>
         <xsl:otherwise>
           <xsl:variable name="vPos" select="position()"/>
           <xsl:variable name="vupdCommand"
                select="$vReps[@line=$vPos]"/>
           <xsl:choose>
             <xsl:when test="$vupdCommand[self::replace]">
              <tr><td><xsl:value-of select="$vupdCommand"/></td></tr>
             </xsl:when>
             <xsl:when test="$vupdCommand[self::insert-before]">
              <tr><td><xsl:value-of select="$vupdCommand"/></td></tr>
              <xsl:call-template name="identity"/>
             </xsl:when>
             <xsl:when test="$vupdCommand[self::insert-after]">
              <xsl:call-template name="identity"/>
              <tr><td><xsl:value-of select="$vupdCommand"/></td></tr>
             </xsl:when>
           </xsl:choose>
         </xsl:otherwise>
        </xsl:choose>
       </xsl:template>
      </xsl:stylesheet>
      

      当此转换应用于当前表时

      <tabe id="realtimetable">
       <tr><td>This is phrase one</td></tr>
       <tr><td>This is phrase two</td></tr>
       <tr><td>This is phrase three</td></tr>
       <tr><td>This is phrase four</td></tr>
      </tabe>
      

      产生想要的正确结果

      <tabe id="realtimetable">
         <tr>
            <td>This is phrase zero (new)</td>
         </tr>
         <tr>
            <td>This is phrase one</td>
         </tr>
         <tr>
            <td>This is new phrase two</td>
         </tr>
         <tr>
            <td>This is phrase four</td>
         </tr>
         <tr>
            <td>This is phrase five (new)</td>
         </tr>
      </tabe>
      

      【讨论】:

      • OP 写道:你的 XSL 看起来很吸引人,我一定会花一些时间来消化它。但是,我(根本)不明白的是如何调用此更新。即我将如何从 JavaScript 触发这种重新转换?
      猜你喜欢
      • 1970-01-01
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 2020-03-23
      • 1970-01-01
      • 2023-02-20
      相关资源
      最近更新 更多