Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6235253
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T10:38:18+00:00 2026-05-24T10:38:18+00:00

I have some XML like this: <story><p><strong>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</strong>Nulla

  • 0

I have some XML like this:

<story><p><strong>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</strong>Nulla vel mauris metus. Etiam vel tortor vel magna bibendum euismod nec varius turpis. Nullam ullamcorper, nunc vel auctor consectetur, quam felis accumsan eros, lacinia fringilla mauris est vel lectus. Curabitur et tortor eros. Duis sed convallis metus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras tempus quam sed enim gravida bibendum. Vestibulum magna ligula, varius in sodales eu, ultricies volutpat sem. Phasellus ante justo, vestibulum eu hendrerit a, posuere vitae est. Integer at pulvinar est.</p><p>Quisque a commodo eros. Integer tempus mi sit amet leo consectetur adipiscing. Nullam sit amet enim metus. Curabitur sollicitudin egestas arcu, at convallis enim iaculis eget. Etiam faucibus, justo sit amet lacinia consectetur, purus nunc rhoncus dui, id malesuada tortor est sed orci. Quisque eget nisi vitae mi facilisis varius. Integer fringilla eros sit amet velit vehicula commodo. </p><br /><span>And some more text here</span>
</story>

I want to do this:

<xsl:copy-of select="substring(story/node(),1,500)"/>

Here is the problem. I lose the <p>, <strong>, <br /> and other HTML tags inside the <story> tag whenever I take the substring. Is there any way to get the first 500 characters of the story tag while keeping the inner HTML tags?

Thanks!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T10:38:19+00:00Added an answer on May 24, 2026 at 10:38 am

    Here is another approach in XSLT 1.0, without having to use the node-set extension:

      <xsl:template match="@*|node()" mode="limit-length">
        <xsl:param name="length"/>
        <xsl:copy>
          <xsl:apply-templates select="@*" mode="limit-length"/>
          <xsl:call-template name="copy-nodes">
            <xsl:with-param name="nodes" select="node()"/>
            <xsl:with-param name="length" select="$length"/>
          </xsl:call-template>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="text()" mode="limit-length">
        <xsl:param name="length"/>
        <xsl:value-of select="substring(., 1, $length)"/>
      </xsl:template>
    
      <xsl:template name="copy-nodes">
        <xsl:param name="nodes"/>
        <xsl:param name="length"/>
        <xsl:if test="$length &gt; 0 and $nodes">
          <xsl:variable name="head" select="$nodes[1]"/>
          <xsl:apply-templates select="$head" mode="limit-length">
            <xsl:with-param name="length" select="$length"/>
          </xsl:apply-templates>
          <xsl:variable name="remaining" select="$length - string-length($head)"/>
          <xsl:if test="$remaining &gt; 0 and count($nodes) &gt; 1">
            <xsl:call-template name="copy-nodes">
              <xsl:with-param name="nodes" select="$nodes[position() &gt; 1]"/>
              <xsl:with-param name="length" select="$remaining"/>
            </xsl:call-template>
          </xsl:if>
        </xsl:if>
      </xsl:template>
    

    Basically this is the identity template, with copying of the child nodes offloaded to a recursive template which takes care of keeping to the maximum string length, plus a separate template for text nodes, truncating them to the maximum length.

    You can invoke this for the sample input as follows:

    <xsl:call-template name="copy-nodes">
      <xsl:with-param name="nodes" select="story/node()"/>
      <xsl:with-param name="length" select="500"/>
    </xsl:call-template>
    

    Follow-up: Splitting the story

    For the follow up question of splitting the story into two pieces after the first break or paragraph end after N characters, I’ll go ahead and make the simplifying assumption that you want to consider splitting only after <p> and <br> elements which appear as direct children under the <story> element (and not nested at an arbitrary depth). This makes the whole problem much easier.

    Here is one way to accomplish it: To get the contents of the first part, you could use a template which will process a set of sibling nodes until the maximum string length is exceeded and a br or p is encountered, and then stop.

      <xsl:template match="node()" mode="before-break">
        <xsl:param name="length"/>
        <xsl:if test="$length &gt; 0 or not(self::br or self::p)">
          <xsl:copy-of select="."/>
          <xsl:apply-templates select="following-sibling::node()[1]"
                               mode="before-break">
            <xsl:with-param name="length" select="$length - string-length(.)"/>
          </xsl:apply-templates>
        </xsl:if>
      </xsl:template>
    

    And for the second part, you could create another template which searches for the same condition as the previous template, but outputs nothing until after that point:

      <xsl:template match="node()" mode="after-break">
        <xsl:param name="length"/>
        <xsl:choose>
          <xsl:when test="$length &gt; 0 or not(self::br or self::p)">
            <xsl:apply-templates select="following-sibling::node()[1]"
                                 mode="after-break">
              <xsl:with-param name="length" select="$length - string-length(.)"/>
            </xsl:apply-templates>
          </xsl:when>
          <xsl:otherwise>
            <xsl:if test="not(self::br)"> <!-- suppress the <br/> -->
              <xsl:copy-of select="."/>
            </xsl:if>
            <xsl:copy-of select="following-sibling::node()"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    

    And here’s how you can use those templates to split a story into two <div>s.

      <xsl:template match="story">
        <xsl:copy>
          <xsl:copy-of select="@*"/>
          <div>
            <xsl:apply-templates select="node()[1]" mode="before-break">
              <xsl:with-param name="length" select="500"/>
            </xsl:apply-templates>
          </div>
          <div>
            <xsl:apply-templates select="node()[1]" mode="after-break">
              <xsl:with-param name="length" select="500"/>
            </xsl:apply-templates>
          </div>
        </xsl:copy>
      </xsl:template>
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have some xml like this: <Data> <Rows> <Row> <Field Name=title>Mr</Field> <Field Name=surname>Doe</Field> <Row>
If I have some xml like this: <mynode> <mysubnode> <mysubsubnode>hello world</mysubsubnode> some more text
I have some XML that is structured like this: <whatson> <productions> <production> <category>Film</category> </production>
I have some XML which contains records and sub records, like this: <data> <record
I have some data in an XML element that looks like this: <?xml version=1.0
Let's suppose I have xml like this one: <Server Active=No> <Url>http://some.url</Url> </Server> C# class
If I have some xml containing things like the following mediawiki markup: ...collected in
I have some values in a configuration file (XML file) with some values like
I have an XML file that I would like to map some attributes of
Lets say i have some code to iterate through an XML file recursively like

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.