【问题标题】:Adding HTML tags with XSLT on the fly使用 XSLT 动态添加 HTML 标记
【发布时间】:2015-07-18 12:15:41
【问题描述】:

我有一个包含以下内容的 XML 文档:

<d1/>
<p1>...</p1>
<p2>...</p2>
<d2/>
<p3>...</p3>
<d3/>

其中 pn 是可能包含子元素和其他内容的元素,而 dn 指示包装 p 标签的 HTML DIV 标记应该从哪里开始,但没有相应的结束标记,这仅由下一个 dn 标记隐式指示。所需的 HTML 输出是这样的:

<div>
<p1>...</p1>
<p2>...</p2>
</div>
<div>
<p3>...</p3>
</div>

我编写了一个 XSLT 来动态引入 &lt;div&gt; 和 &lt;/div&gt; 标签,使用以下代码:

<xsl:text disable-output-escaping="yes">&lt;div&gt;</xsl:text>

和

<xsl:text disable-output-escaping="yes">&lt;/div&gt;</xsl:text>

这在 Safari 上有效,但在 FireFox 上失败,这让我怀疑这不是正确的方法。 您是否有更好的想法适用于所有浏览器?

非常感谢。

【问题讨论】:

  • 标签的编号真的和你显示的一样吗?如果是,您真的要在输出中保留 p 标记的编号吗?
  • 不,这只是一个例子。它是不同标签的混合。
  • 那么究竟如何识别“divider”标签呢?
  • 分隔标签是这样的,我说的是p标签。
  • 这并不能真正回答我的问题。这里的问题是*[starts-with(name(), 'd')](Martin Honnen 和我都使用过)是否选择 only 分隔符标签。 -- 也不清楚你想如何处理其他节点;两个答案(现在)都假设您要按原样复制它们。

标签: html xml xslt


【解决方案1】:

Firefox 不支持禁用输出转义,因为它不序列化结果树。该问题是一个分组问题,解决它的一种方法是使用密钥:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output indent="yes"/>

<xsl:key name="group" match="body/*[not(starts-with(local-name(), 'd'))]" use="generate-id(preceding-sibling::*[starts-with(local-name(), 'd')][1])"/>

<xsl:template match="body">
    <xsl:copy>
        <xsl:apply-templates select="*[starts-with(local-name(), 'd')]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*[starts-with(local-name(), 'd')]">
    <div>
        <xsl:copy-of select="key('group', generate-id())"/>
    </div>
</xsl:template>
</xsl:transform>

这会在示例结束时创建一个空的div,因此您可能需要将最后一个模板更改为

<xsl:template match="*[starts-with(local-name(), 'd')]">
    <xsl:if test="key('group', generate-id())">
      <div>
        <xsl:copy-of select="key('group', generate-id())"/>
      </div>
    </xsl:if>
</xsl:template>

【讨论】:

    【解决方案2】:

    您可以使用一种称为“兄弟递归”的技术。

    给定一个格式良好的输入,例如:

    XML

    <root>
        <d1/>
        <p1>a</p1>
        <p2>b</p2>
        <d2/>
        <p3>c</p3>
        <d3/>
    </root>
    

    以下样式表:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"/>
    
    <xsl:template match="/root">
        <body>
            <xsl:apply-templates select="*[starts-with(name(), 'd')][position()!=last()]"/>
        </body>
    </xsl:template>
    
    <xsl:template match="*[starts-with(name(), 'd')]">
        <div>
            <xsl:apply-templates select="following-sibling::*[1][not(starts-with(name(), 'd'))]"/>
        </div>
    </xsl:template>
    
    <xsl:template match="/root/*[not(starts-with(name(), 'd'))]">
        <xsl:copy-of select="."/>
        <xsl:apply-templates select="following-sibling::*[1][not(starts-with(name(), 'd'))]"/>
    </xsl:template>
    
    </xsl:stylesheet>
    

    将返回:

    <body>
       <div>
          <p>a</p>
          <p>b</p>
       </div>
       <div>
          <p>c</p>
       </div>
    </body>
    

    【讨论】:

      猜你喜欢
      • 2021-10-06
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      • 2010-11-30
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 2019-08-30
      相关资源
      最近更新 更多