使用不同的XSLT生成各种结果

时间:2017-10-10 20:30:58

标签: xml xslt replace

我使用我的软件创建XML(即我可以控制其结构)。我想使用此XML通过使用不同的XSLT转换文件生成不同的结果。如何在结果中生成不同的文本,具体取决于使用的XSLT?

更具体:

我的结果文件应包含“点”字符,即。即或三个点,i。即...,取决于使用的XSLT。使用一个XSLT,我的XML将导致第一个,而另一个XSLT,相同的XML(!)将导致第二个。我需要编写XSLT,以便将XML转换为一次,一次转换为另一种。

我的第一个方法是替换输入的子字符串。针对这个主题存在各种其他问题,但到目前为止还不适合我的情况:

  • 在XML中使用,然后在XSLT中使用replace() - 但我使用的XSLT 1.0不包含这个不错的功能。
  • 在XML中使用,然后在XSLT中使用translate() - 但这只能将一个字符转换为一个字符,而我需要将...作为输出之一(即不止一个字符。)
  • 在XML中使用实体(例如&dots;)并让XSLT将它们扩展为不同的字符串 - 这样做的唯一方法我发现实体与任何其他字符串完全相同,因此找不到解决方案。我仍然希望我使用这种方法找不到一个简单易用的解决方案。

在XSLT 1.0中实现类似replace()的东西有很多费力的解决方案。在使用这些之前,我宁愿创建不同的XML: - /

我很惊讶我的问题似乎很难解决,并且感觉我忽略了一些简单的事情。

3 个答案:

答案 0 :(得分:1)

XSLT,尤其是版本1.0,具有更粗略的焦点,并且比您想要的更简约。它适用于处理节点,子节点及其值,但其内置的字符串操作功能有限。如果您不准备使用扩展函数,那么这意味着您可能需要为某些事情编写自己的XSLT。

例如,假设您生成包含单字符elipses的XML。您的其中一个转换可以直接传递这些转换。你的另一个可能会使用这样的机制将它们转换成三个点:

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

  <xsl:template match="text()">
    <xsl:call-template name="translate-elipsis">
      <xsl:with-param name="text" select="."/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="translate-elipsis">
    <xsl:param name="text"/>
    <xsl:choose>
      <xsl:when test="contains($text,'…')">
        <xsl:value-of select="substring-before($text,'…')"/>
        <xsl:text>...</xsl:text>
        <xsl:call-template name="translate-elipsis" select="substring-after($text,'…')"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

转换没有更具体匹配的所有文本节点的内容;如果需要,您也可以使用它来转换属性值。我认为它肯定比单个函数调用更冗长,但并非离谱。您可以使用类似的模式来编写用于字符串替换的通用模板。

答案 1 :(得分:1)

正如你所说,你掌握了XML,似乎只有一种方法就是在它自己的元素中标记特定数据,例如

<p>This is a text with an <ellipsis/>.</p>

然后在样式表中你想拥有三个点你只需要一个模板

<xsl:template match="ellipsis">
  <xsl:text>...</xsl:text>
</xsl:template>

其他样式表将输出字符

<xsl:template match="ellipsis">
  <xsl:text>…</xsl:text>
</xsl:template>

除此之外,我同意所提出的建议和意见,现在Java平台上支持XSLT 2.0甚至3.0,没有人被迫在JRE中使用FOP和内置的XSLT 1.0处理器。

答案 2 :(得分:0)

我使用来自https://stackoverflow.com/a/12364925/1281485的一些建议解决了FOP的问题: 添加一些名称空间后,我可以访问replaceAll(),它按预期工作:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:xalan="http://xml.apache.org/xalan"
                xmlns:str="xalan://java.lang.String">

以后:

  <xsl:template match="text()">
    <xsl:value-of select="str:replaceAll(str:new(.), '…', '...')"/>
  </xsl:template>

如果我将来发现任何问题,我可能会更新我的答案。到目前为止,它似乎解决了我的任务。