Trim whitespace from parent element only

前端 未结 3 666
粉色の甜心
粉色の甜心 2020-12-21 12:31

I\'d like to trim the leading whitespace inside p tags in XML, so this:

Hey, italics and italics!

相关标签:
3条回答
  • 2020-12-21 12:47

    This stylesheet:

    <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="p//text()[1][generate-id()=
                                          generate-id(ancestor::p[1]
                                                      /descendant::text()[1])]">
            <xsl:variable name="vFirstNotSpace"
                          select="substring(normalize-space(),1,1)"/>
            <xsl:value-of select="concat($vFirstNotSpace,
                                         substring-after(.,$vFirstNotSpace))"/>
        </xsl:template>
    </xsl:stylesheet>
    

    Output:

    <p>Hey, <em>italics</em> and <em>italics</em>!</p>
    

    Edit 2: Better expression (now only three function calls).

    Edit 3: Matching the first descendant text node (not just the first node if it's a text node). Thanks to @Dimitre's comment.

    Now, with this input:

    <p><b>  Hey, </b><em>italics</em> and <em>italics</em>!</p>
    

    Output:

    <p><b>Hey, </b><em>italics</em> and <em>italics</em>!</p>
    
    0 讨论(0)
  • 2020-12-21 12:56

    You want:

     <xsl:template match="text()">
      <xsl:value-of select=
       "substring(
           substring(normalize-space(concat('[',.,']')),2),
           1,
           string-length(.)
                  )"/>
     </xsl:template>
    

    This wraps the string in "[]", then performs normalize-string(), then finally removes the wrapping characters.

    0 讨论(0)
  • 2020-12-21 13:00

    I would do something like this:

    <xsl:template match="p">
        <xsl:apply-templates/>
    </xsl:template>
    
    <!-- strip leading whitespace -->
    <xsl:template match="p/node()[1][self::text()]">
      <xsl:call-template name="left-trim">
         <xsl:with-param name="s" value="."/>
      </xsl:call-template>
    </xsl:template>
    

    This will strip left space from the initial node child of a <p> element, if it is a text node. It will not strip space from the first text node child, if it is not the first node child. E.g. in

    <p><em>Hey</em> there</p>
    

    I intentionally avoid stripping the space from the front of 'there', because that would make the words run together when rendered in a browser. If you did want to strip that space, change the match pattern to

    match="p/text()[1]"
    

    If you also want to strip trailing whitespace, as your title possibly implies, add these two templates:

    <!-- strip trailing whitespace -->
    <xsl:template match="p/node()[last()][self::text()]">
      <xsl:call-template name="right-trim">
         <xsl:with-param name="s" value="."/>
      </xsl:call-template>
    </xsl:template>
    
    <!-- strip leading/trailing whitespace on sole text node -->
    <xsl:template match="p/node()[position() = 1 and
                                  position() = last()][self::text()]"
                  priority="2">
       <xsl:value-of select="normalize-space(.)"/>
    </xsl:template>
    

    The definitions of the left-trim and right-trim templates are at Trim Template for XSLT (untested). They might be slow for documents with lots of <p>s. If you can use XSLT 2.0, you can replace the call-templates with

      <xsl:value-of select="replace(.,'^\s+','')" />
    

    and

      <xsl:value-of select="replace(.,'\s+$','')" />
    

    (Thanks to Priscilla Walmsley.)

    0 讨论(0)
提交回复
热议问题