通过XSLT

时间:2015-09-28 23:02:33

标签: json xslt xslt-2.0

巨大的免责声明注意:这仅适用于您处理生成的html表格时,本地翻译HTML实体双引号,否则XSLT处理器应该生成甚至生成在普通的双引号包装属性中。 (例如")。我当然意识到逃脱的双引号实际上只是在我写完之后才能满足我的需求,因为我试过的第一件事是单引号,它没有解析为JSON,而且我已经碰到了敏感之前的JSON解析情况所以我甚至没想过只使用元素转义的双引号,但这可能仍然有利于其他一些情况(参见:敏感的JSON解析情况),所以我要继续前进发布它。

简明扼要地说:您不需要为JSON执行所有这些操作,而现有的基于浏览器的解析器将对其执行操作。 HTML实体双引号(")是那些有效的分隔符(是的,甚至是IE)。

通过XSLT(特别是用于初始化滑块的HTML5数据属性)将JSON构建到HTML元素属性中,我遇到了令人沮丧的难题。

XSLT仅将属性处理为包含在双引号内。 (注意:如果有一个可以交换它的处理标志/指令,它需要是我可以从工作表内部调用的,而不是从启动调用到处理器,因为我无法控制它)。 / p>

JSON要求双引号有效。

主要处理细节:我在Saxon 9.3.0.5中工作,并且由一个我无法直接访问修改(专有CMS代码)的系统调用和初始化。

我可以(?)在javascript中解决这个问题,但是如果我已经忽略了原生的XSLT解决方案,那么很高兴知道。我假设没有,因为从2013年开始comment from Michael Kay,他开玩笑说属性包装选择如何一直是不可改变的,因为应该没有世俗的理由需要来改变它。我通常会同意,直到现在,我实际上需要它,因为双引号属性中的JSON的单引号实际上是无效的JSON。 编辑:请参阅免责声明,即使是99%的JSON相关案例,他仍然可能是正确的。

我可能在脚本元素或类似的东西中构建一个单独的JSON字符串,然后在相关的滑块函数运行之前通过javascript将其注入属性,这可能是我应该的当我重构这个时,我会想知道其他选项是什么,如果有的话。

我将使用非本地/正确的XSLT解决方案来解决这个问题,这个解决方案适用于遇到类似问题的其他任何人,但我真的想要更好的东西它在那里,因为我讨厌在XSL中使用这种类型的黑客。

示例代码(减去许多周围的匹配,标识xform等):

(问题特定于将匹配的ul中的' data-slick'属性添加到此处)

<xsl:template match="mus:call-template[@name='slick-slider-carousel']//ul">
    <xsl:param name="slider-options" tunnel="yes" />
    <xsl:param name="pcf-context" tunnel="yes" />
    <xsl:copy copy-namespaces="no">
        <xsl:apply-templates select="@attribute" />
        <xsl:attribute name="data-slick"><xsl:text>{</xsl:text>
            <xsl:apply-templates select="$slider-options" />
            <xsl:text>}</xsl:text>
        </xsl:attribute>
        <xsl:apply-templates select="$pcf-context/gallery/images/image" mode="slick-slider">
            <xsl:with-param name="asset-id" select="$pcf-context/gallery/@asset-id" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

示例html布局表:

    <mus:call-template name="slick-slider-carousel">
        <div class="image-carousel">
            <ul>
            </ul>
        </div>
    </mus:call-template>

从内容表加载到$ pcf-context中的示例树片段(通过xsl:sequence):

<gallery created="2015-03-25T21:18:20Z" forceCrop="false" modified="2015-03-25T21:19:31Z" asset_id="649">
  <name>Test</name>
  <thumbnailWidth>100</thumbnailWidth>
  <thumbnailHeight>100</thumbnailHeight>
  <forceCrop>false</forceCrop>
  <advanced>
  </advanced>
  <images>
    <image created="2015-03-25T21:18:53Z" modified="2015-03-25T21:18:53Z" staging_url="[full-url]/6d640b3f-7e50-4bdf-802d-2d5e33955ed1.jpeg" url="[full-url]/6d640b3f-7e50-4bdf-802d-2d5e33955ed1.jpeg" status="existing">
      <storedName>6d640b3f-7e50-4bdf-802d-2d5e33955ed1.jpeg</storedName>
      <friendlyName>d01454b9-5eab-4a7f-b999-3ec92313b193.jpeg</friendlyName>
      <thumbnail staging_url="[full-url]/thumb/6d640b3f-7e50-4bdf-802d-2d5e33955ed1.jpeg" url="[full-url]/6d640b3f-7e50-4bdf-802d-2d5e33955ed1.jpeg">
        <width>100</width>
        <height>100</height>
      </thumbnail>
      <title>A very cute puppy</title>
      <description>Cute puppy</description>
      <caption>Look at that cute puppy! lorem ipsum blah blah blah</caption>
      <link>
      </link>
    </image>
  </images>
</gallery>

1 个答案:

答案 0 :(得分:0)

手动构建具有属性结构的HTML元素(在属性值上使用单引号外包装分隔符)

这是一个hack,因为它不是在结果树中生成元素,而是在浏览器加载输出表时生成充当DOM节点的文本......但这些仍然不是XSLT处理器中的实际元素< / strong>即可。我真的不建议您使用此方法,除非绝对需要它:

<xsl:template match="mus:call-template[@name='slick-slider-carousel']//ul">
    <xsl:param name="slider-options" tunnel="yes" />
    <xsl:param name="pcf-context" tunnel="yes" />
    <xsl:text disable-output-escaping="yes">&lt;ul</xsl:text>
        <xsl:apply-templates select="attribute()" mode="textify" />
        <xsl:text> data-slick='{</xsl:text>
        <xsl:apply-templates select="$slider-options" />
        <xsl:text>}'</xsl:text>
        <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
        <xsl:apply-templates select="$pcf-context/gallery/images/image" mode="slick-slider">
            <xsl:with-param name="asset-id" select="$pcf-context/gallery/@asset-id" />
        </xsl:apply-templates>
    <xsl:text disable-output-escaping="yes">&lt;/ul&gt;</xsl:text>
</xsl:template>

<xsl:template match="attribute()" mode="textify">
    <xsl:text> </xsl:text>
    <xsl:value-of select="local-name()" />
    <xsl:text>='</xsl:text>
    <xsl:value-of select="." />
    <xsl:text>'</xsl:text>
</xsl:template>

要注意的要点:

  1. disable-output-escaping:您需要在要生成html元素的文本节点上,或者更具体地说,在它们的开放和结束方括号(lt和gt)上。
  2. 如果您在此范围内使用apply-templates,请非常了解结果的相互作用方式。例如,尝试将其属性添加到当前元素的任何属性模板(通过标识转换等)将失败或将其添加到父元素,因为此处创建的html元素实际上不是XSLT元素,而不是附加属性的有效目标。如果要使用apply-templates,则需要具有将它们转储为文本而不是将它们作为节点进行操作的备用模式匹配(请参阅包含属性的“textify”模式的示例)。
  3. 与2一致,您必须手动构建要添加的任何属性。注意空间! (参见主要比赛中@ data-slick的建设)
  4. 使用<xsl:text>对您有利:如果使用正确,这将允许您在xsl:text元素之间为代码提供一些线条间距,使其比单个<xsl:value-of select="concat(stuff, more stuff, too much more stuff, etc)" />更清晰
  5. (个人偏好)如果您要转发已存在的属性(身份转换样式),请使用模态apply-templates而不是for-each。它不仅更清晰,而且更像是一种声明范式,但它也更具可重用性。请注意,如果您手动构建的任何属性已经存在,则需要提供一个排除它们的逻辑路径(例如特定于该属性的模板匹配以丢弃它们)或提供一种方法来手动添加它们不存在或附加他们的信息(多种方式可以做到这一点,我个人觉得apply-templates属性处理的方法使大多数人更清洁。)