【问题标题】:XSLT multiple replacingXSLT 多重替换
【发布时间】:2011-01-08 05:02:14
【问题描述】:

我有一个 XML 文档,类似于

<root>
  <item>_x0034_SOME TEXT</item>
  <item>SOME_x0020_TEXT</item>
  <item>SOME_x0020_TEXT_x0032_</item>
</root>

我正在将其导出为 HTML,但在替换转义字符时遇到问题。 我在网上找到了几个模板来进行文本替换,但它们都类似于:

<xsl:template name="replaceString">
    <xsl:param name="strOrig"/>
    <xsl:param name="strSearch"/>
    <xsl:param name="strReplace"/>
    <xsl:choose>
        <xsl:when test="contains($strOrig, $strSearch)">
            <xsl:value-of select="substring-before($strOrig, $strSearch)"/>
            <xsl:value-of select="$strReplace"/>
            <xsl:call-template name="replaceString">
                <xsl:with-param name="strOrig" select="substring-after($strOrig, $strSearch)"/>
                <xsl:with-param name="strSearch" select="$strSearch"/>
                <xsl:with-param name="strReplace" select="$strReplace"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$strOrig"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

我不确定如何使用它来进行多次替换。我试过这个:

<xsl:for-each select="PinnacleSys.PMC.Plugins.PVR.PvrChannelDescriptorWrapper/PinnacleSys.PMC.Plugins.PVR.DVBTPvrChannelDescriptor">

    <!--name="<xsl:value-of select="replace(replace(Name, '_x0020_', ' '), '_x0034_', '3')"/>" -->
    <!--name="<xsl:value-of select="Name"/>"-->
    <xsl:variable name="var1" select="Text" />
        <xsl:value-of select="replace($FeatureInfo,'Feature=','TESTING')"/>

    name="
        <xsl:call-template name="replaceString">
            <xsl:with-param name="strOrig" select="Name"/>
            <xsl:with-param name="strSearch" select="'_x0020_'"/>
            <xsl:with-param name="strReplace" select="' '"/>
        </xsl:call-template>
        <xsl:call-template name="replaceString">
            <xsl:with-param name="strOrig" select="Name"/>
            <xsl:with-param name="strSearch" select="'_x0030_'"/>
            <xsl:with-param name="strReplace" select="'0'"/>
        </xsl:call-template>
       ..."

但这只是将字符串连接多次,每次都有不同的替换。 我还研究了变量;如果我可以将模板调用的结果分配给一个变量,我可以获得一个肮脏但有效的解决方案,这对我来说已经足够了。但是我一直无法也不知道是否有可能。

最好的方法是什么?

我仅限于 1.0 XSLT(使用 2.0 我可以在另一个内部调用一个 replace())。

【问题讨论】:

  • 您使用的是什么解析器? msxml, .net?
  • 目前我用的是IE8.0,所以我猜是msxml。

标签: xml xslt replace


【解决方案1】:

对于使用模板进行替换的本机 XSLT 1.0 解决方案,需要嵌套各个替换,如此处所示。由于潜在的替换数量,这显然不是有效的。下面给出一个优化的版本。

<xsl:template match="item">
<xsl:copy>
    <xsl:call-template name="replace-substring">
        <xsl:with-param name="original">
            <xsl:call-template name="replace-substring">
                <xsl:with-param name="original">
                    <xsl:call-template name="replace-substring">
                        <xsl:with-param name="original" select="."/>
                        <xsl:with-param name="substring" select="'_x0020_'"/>
                        <xsl:with-param name="replacement" select="' '"/>
                    </xsl:call-template>
                </xsl:with-param>
                <xsl:with-param name="substring" select="'_x0032_'"/>
                <xsl:with-param name="replacement" select="'2'"/>
            </xsl:call-template>
        </xsl:with-param>
        <xsl:with-param name="substring" select="'_x0034_'"/>
        <xsl:with-param name="replacement" select="'4'"/>
    </xsl:call-template>
</xsl:copy>
</xsl:template>

<xsl:template name="replace-substring">
<xsl:param name="original"/>
<xsl:param name="substring"/>
<xsl:param name="replacement" select="''"/>
<xsl:choose>
    <xsl:when test="contains($original, $substring)">
        <xsl:value-of select="substring-before($original, $substring)"/>
        <xsl:copy-of select="$replacement"/>
        <xsl:call-template name="replace-substring">
            <xsl:with-param name="original" select="substring-after($original, $substring)"/>
            <xsl:with-param name="substring" select="$substring"/>
            <xsl:with-param name="replacement" select="$replacement"/>
        </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="$original"/>
    </xsl:otherwise>
</xsl:choose>
</xsl:template>

由于输出是 HTML(XML 也可以),_xNNNN_ 字符串可以转换为它们的十六进制数字字符引用,例如,&amp;#xNNNN;。这个模板很有效。

<xsl:template match="item">
<xsl:copy>
    <xsl:call-template name="replaceChars">
        <xsl:with-param name="original" select="."/>
    </xsl:call-template>
</xsl:copy>
</xsl:template>

<xsl:template name="replaceChars">
<xsl:param name="original"/>
<xsl:choose>
    <xsl:when test="contains($original, '_x')">
        <xsl:value-of select="substring-before($original, '_x')"/>
        <xsl:variable name="after" select="substring-after($original, '_x')"/>
        <xsl:variable name="char" select="substring-before($after, '_')"/>
        <xsl:value-of select="concat('&amp;#x',$char,';')" disable-output-escaping="yes"/>
        <xsl:call-template name="replaceChars">
            <xsl:with-param name="original" select="substring-after($after, '_')"/>
        </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="$original"/>
    </xsl:otherwise>
</xsl:choose>
</xsl:template>

这是结果输出。

<root>
    <item>&#x0034;SOME TEXT</item>
    <item>SOME&#x0020;TEXT</item>
    <item>SOME&#x0020;TEXT&#x0032;</item>
</root>

【讨论】:

    【解决方案2】:

    查看 EXSLT (www.exslt.org) 中的正则表达式支持。大多数现代 XSL 处理器都支持 EXSLT。

    【讨论】:

      【解决方案3】:

      在变量主体内调用模板。

      <xsl:variable name="myVar"><xsl:call-template name="replaceString">
              <xsl:with-param name="strOrig" select="Name"/>
              <xsl:with-param name="strSearch" select="'_x0020_'"/>
              <xsl:with-param name="strReplace" select="' '"/>
          </xsl:call-template>
      </xsl:variable>
      

      这分配给调用的 myVar 内容。

      【讨论】:

        【解决方案4】:

        XSLT 1.0 在字符串替换方面并不是最好的。您拥有的模板将是使用的模板。但是,对于字符串替换,我使用另一种语言的字符串替换,通常是 JavaScript 或 C#/VB.NET(Java 或任何其他语言也可以)。据推测,在某些时候,XML 文档被序列化为字符串。一旦它是一个字符串,使用简单的字符串到字符串替换或正则表达式来进行更复杂的模式匹配。

        【讨论】:

        • 正如我上面所说的,我正在使用 IE8 解析功能,以避免编程。因此,如果我找到原生 XSLT 解决方案,我不会尝试这个。不过谢谢。
        • 我后面的回答中给出了原生 XSLT 解决方案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-05
        • 1970-01-01
        • 2014-07-26
        • 2011-04-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多