damien535
damien535

Reputation: 637

xml xslt question

I have an xml that has text within "word" elements e.g

<word>Police</word>
<word>confirmed</word>
<word>they are</word>
<word>questioning</word>
<word>a</word>
<word>man</word>

The problem is when I apply the xslt the text appears like "Policeconfirmedthey arequestioningaman".

Here is the xslt snippet that does this transform

<Paragraph>
 <xsl:for-each select="./speaker/segment">
 <xsl:value-of select="./nbest"/>
 </xsl:for-each>
</Paragraph>

Can anyone offer any help as to how I can display this as "Police confirmed they are questioning a man"?

Many thanks.

Upvotes: 1

Views: 1178

Answers (6)

Nehan
Nehan

Reputation: 1

By using normalize-space(), we can remove the whitespaces.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Identity template: copies everything as is -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
 
    <!-- Template to match <root> element and concatenate text content -->
<xsl:template match="root">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
</xsl:stylesheet>

Upvotes: 0

null
null

Reputation: 7594

The reason they are running together is because the stylesheet is using a built-in template to match against which is collapsing the white space. I don't see where you are explicitly calling the <word/> or surrounding XML, so I'm assuming it's an <xsl:apply-templates /> call somewhere. You should just need to just define a match template as such:

<xsl:template match="word">
    <xsl:value-of select="." />&#160;
</xsl:template>

Whitespace is significant, so if in the above solution, you find it messing things up, you can wrap the   within an <xsl:text/> node, and whitespace be gone.

Then when the word node is matched you get it spaced. Note: there will be an extra space at the end. To get rid of that it will be slightly longer.

<xsl:temmplate match="word">
    <xsl:value-of select="." />
    <xsl:if test=". !=../word[last()]">
        <xsl:text>&#160;</xsl:text>
    </xsl:if>
</xsl:template> 

This will only work when applying-templates, and not when using value-of or copy-of xsl directives.

Upvotes: 2

Schwartser
Schwartser

Reputation: 93

it is almost like "aku" answer. But "aku" answer creats one paragraph.

 <xsl:for-each select="./speaker/segment">  
 <Paragraph>   
    <xsl:for-each select="./nbest/word"/>        
      <xsl:value-of select="."/>
        <xsl:if test="position()!=last()">
          <xsl:text> </xsl:text>
        </xsl:if>        
    </xsl:for-each>
 </Paragraph>
</xsl:for-each>

Upvotes: 2

aku
aku

Reputation: 123956

You can conditionally add a space between words based on word's position. The following snippet shows how to add a whitespace after all but last word.

<xsl:template match="//words">
    <xsl:for-each select="word">
      <xsl:value-of select="."/>
      <!-- Check word's position -->
      <xsl:if test="position()!=last()">
      <!-- Add a whitespace if it's not the last word -->
        <xsl:text> </xsl:text>
      </xsl:if>
    </xsl:for-each>
</xsl:template>

If you produce HTML output, you can use info from this post to find out how to add a whitespace (instead of < xst:text > in my code snippet)

Upvotes: 4

annakata
annakata

Reputation: 75794

Add a space character.

Simple way:

<Paragraph>
 <xsl:for-each select="./speaker/segment">
   <xsl:value-of select="./nbest"/>&#160;
 </xsl:for-each>
</Paragraph>

Slightly more complex way to effectively trim the string:

<Paragraph>
 <xsl:for-each select="./speaker/segment">
   <xsl:if test="not(position() = 1)">&#160;</xsl:if>
   <xsl:value-of select="./nbest"/>
 </xsl:for-each>
</Paragraph>

And some xpath ways: normalize-space, substring-before, substring-after in various forms.

Upvotes: 3

rravuri
rravuri

Reputation: 421

try this adding &npsp; after valueof tag

Upvotes: 0

Related Questions