代码之家  ›  专栏  ›  技术社区  ›  Ace

XSL:用xml标记替换某些字符

  •  6
  • Ace  · 技术社区  · 15 年前

    这个有点棘手,我已经坚持了一段时间了。我想做的是把标签放在括号“[”的位置(例如,按钮、链接等),并放在“]的位置

    <section>
        <title>Buttons</title>
        <orderedlist>
            <listitem>
                <para>Clicking on [Save] will attempt to save changes, then it navigates to <xref linkend="saved" xrefstyle="select: title"/>.</para>
            </listitem>
            <listitem>
                <para>Clicking on [Cancel] navigates to <xref linkend="noSave" xrefstyle="select: title"/>.</para>
            </listitem>
        </orderedlist>
    </section>
    

    致:

    <section>
        <title>Buttons</title>
        <orderedlist>
            <listitem>
                <para>Clicking on <uicontrol>Save</uicontrol> will attempt to save changes, then it navigates to <xref linkend="saved" xrefstyle="select: title"/>.</para>
            </listitem>
            <listitem>
                <para>Clicking on <uicontrol>Cancel</uicontrol> navigates to <xref linkend="noSave" xrefstyle="select: title"/>.</para>
            </listitem>
        </orderedlist>
    </section>
    

    “[']”不一定总是在section.listitem.para中

    编辑:

    3 回复  |  直到 15 年前
        1
  •  2
  •   Dimitre Novatchev    15 年前

    这种转变

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my" exclude-result-prefixes="my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <my:uicontrols>
      <control>[Save]</control>
      <control>[Cancel]</control>
     </my:uicontrols>
    
     <xsl:key name="kHasControls" match="text()"
      use="boolean(document('')/*/my:uicontrols/*[contains(current(), .)])"/>
    
     <xsl:variable name="vControls" select="document('')/*/my:uicontrols/*"/>
    
     <xsl:template match="node()|@*" name="identity">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="text()[key('kHasControls', 'true')]">
      <xsl:choose>
       <xsl:when test="not($vControls[contains(current(),.)])">
         <xsl:copy-of select="."/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:call-template name="createControl"/>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    
     <xsl:template name="createControl">
      <xsl:param name="pText" select="."/>
    
      <xsl:choose>
       <xsl:when test="not(contains($pText, '['))">
        <xsl:copy-of select="$pText"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:copy-of select="substring-before($pText, '[')"/>
    
         <xsl:variable name="vStartText" select=
         "concat('[', substring-after($pText, '['))"/>
         <xsl:variable name="vCtrl" select="$vControls[starts-with($vStartText,.)]"/>
         <xsl:choose>
          <xsl:when test="not($vCtrl)">
           <xsl:text>[</xsl:text>
           <xsl:call-template name="createControl">
             <xsl:with-param name="pText" select="substring($vStartText,1)"/>
           </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
           <uicontrol>
            <xsl:value-of select="translate($vCtrl,'[]','')"/>
           </uicontrol>
    
           <xsl:call-template name="createControl">
             <xsl:with-param name="pText" select="substring-after($vStartText, $vCtrl)"/>
           </xsl:call-template>
          </xsl:otherwise>
         </xsl:choose>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    </xsl:stylesheet>
    

    当应用于所提供的XML文档时 :

    <section>
        <title>Buttons</title>
        <orderedlist>
            <listitem>
                <para>Clicking on [Save] will attempt to save changes, then it navigates to <xref linkend="saved" xrefstyle="select: title"/>.</para>
            </listitem>
            <listitem>
                <para>Clicking on [Cancel] navigates to <xref linkend="noSave" xrefstyle="select: title"/>.</para>
            </listitem>
        </orderedlist>
    </section>
    

    产生想要的正确结果

    <section>
        <title>Buttons</title>
        <orderedlist>
            <listitem>
                <para>Clicking on <uicontrol>Save</uicontrol><xref linkend="saved" xrefstyle="select: title"/>.</para>
            </listitem>
            <listitem>
                <para>Clicking on <uicontrol>Cancel</uicontrol><xref linkend="noSave" xrefstyle="select: title"/>.</para>
            </listitem>
        </orderedlist>
    </section>
    

    注意以下几点

    1. 此解决方案仅替换控件名称的受控列表 "[Anything]" 没有任何问题(例如,我们想显示一个著名的XPath表达式——这样的表达式按定义有谓词:)

    2. 钥匙的使用保证了更好的效率 "[" .

        2
  •  3
  •   user357812 user357812    15 年前

    uicontrol 对于嵌套方括号(需要对平衡方括号和非平衡方括号进行解析)。

    此样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
     <xsl:template match="text()" name="replace" priority="1">
      <xsl:param name="pString" select="."/>
      <xsl:variable name="vMask" select="translate($pString,
                                                         translate($pString,
                                                                   '[]',
                                                                   ''),
                                                         '')"/>
      <xsl:choose>
       <xsl:when test="contains($vMask,'[]')">
        <xsl:call-template name="makeControl">
         <xsl:with-param name="pString" select="$pString"/>
         <xsl:with-param name="pMask"
                         select="substring-before($vMask,'[]')"/>
        </xsl:call-template>
       </xsl:when>
       <xsl:otherwise>
        <xsl:value-of select="$pString"/>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
     <xsl:template name="makeControl">
      <xsl:param name="pString"/>
      <xsl:param name="pMask"/>
      <xsl:choose>
       <xsl:when test="$pMask">
        <xsl:variable name="vMask" select="substring($pMask,1,1)"/>
        <xsl:value-of select="concat(
                                 substring-before(
                                    $pString,
                                    $vMask),
                                 $vMask)"/>
        <xsl:call-template name="makeControl">
         <xsl:with-param name="pString"
                         select="substring-after($pString,$vMask)"/>
         <xsl:with-param name="pMask" select="substring($pMask,2)"/>
        </xsl:call-template>
       </xsl:when>
       <xsl:otherwise>
        <xsl:value-of select="substring-before($pString,'[')"/>
        <uicontrol>
         <xsl:value-of select="substring-before(
                                                 substring-after(
                                                    $pString,
                                                    '['),
                                                 ']')"/>
        </uicontrol>
        <xsl:call-template name="replace">
         <xsl:with-param name="pString"
                                        select="substring-after($pString,']')"/>
        </xsl:call-template>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    </xsl:stylesheet>
    

    <section>
     <title>Buttons</title>
     <orderedlist>
      <listitem>
       <para>Clicking on <uicontrol>Save</uicontrol> will attempt to save changes, then it navigates to <xref linkend="saved" xrefstyle="select: title"></xref>.</para>
      </listitem>
      <listitem>
       <para>Clicking on <uicontrol>Cancel</uicontrol> navigates to <xref linkend="noSave" xrefstyle="select: title"></xref>.</para>
      </listitem>
     </orderedlist>
    </section>
    

    有了这个输入:

    <text>
    This is an opening bracket [ ? [Yes] [No]
    This is a closing bracket ] ? [Yes] [No]
    </text>
    

    <text>
    This is an opening bracket [ ? <uicontrol>Yes</uicontrol> <uicontrol>No</uicontrol>
    This is a closing bracket ] ? <uicontrol>Yes</uicontrol> <uicontrol>No</uicontrol>
    </text>
    

    注意 :任何匹配的文本 \[[^\[\]]*\] 会被包装成 第二季

        3
  •  2
  •   Lucero    15 年前

    你可以和 contains , substring-before substring-after

    编辑-应该有用:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
        <xsl:output method="xml" indent="yes"/>
    
        <xsl:template name="insertElements">
            <xsl:param name="text" select="." />
            <xsl:choose>
                <xsl:when test="contains($text, '[')">
                    <xsl:value-of select="substring-before($text, '[')"/>
                    <xsl:variable name="after" select="substring-after($text, '[')" />
                    <uicontrol>
                        <xsl:value-of select="substring-before($after, ']')"/>
                    </uicontrol>
                    <xsl:call-template name="insertElements">
                        <xsl:with-param name="text" select="substring-after($after, ']')" />
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$text"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@*"/>
                <xsl:for-each select="node()">
                    <xsl:choose>
                        <xsl:when test="self::text()">
                            <xsl:call-template name="insertElements" />
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="." />
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>