7

Rewrite without & lt; xsl: for-each & gt ;; select all text separated by...

 3 years ago
source link: https://www.codesd.com/item/rewrite-without-xsl-for-each-select-all-text-separated-by-spaces-dropping-text-with-an-attribute.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Rewrite without & lt; xsl: for-each & gt ;; select all text separated by spaces; dropping text with an attribute

advertisements

I have the following XSL working but there should be a way to rewrite it without using the xsl:for-each element. I need to take an arbitrary block of XML, drop all elements that have a 'drop' attribute and concatenate the remaining text with spaces without adding extra spaces at the end or end of the concatenated text.

I should say that the only part of the XML I can key off of is the 'drop' attribute. I cannot key off of any of element names like 'testing', 'catalog', 'book', etc.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/*">
        <xsl:for-each select="//*[not(@drop)]/text()">
            <xsl:value-of select="."/>
            <xsl:if test="position() != last()">
                <xsl:text> </xsl:text>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

The XML I've been testing with:

<testing>
    <text drop="meta">Drop this meta</text>
    <catalog>
        <book id="bk101">
            <text drop="stuff">Drop this stuff</text>
            <title ti="Full Title">XML Developer\ts Guide</title>
            <author>Gambardella, Matthew</author>
        </book>
    </catalog>
</testing>

and the valid output:

XML Developer   s Guide Gambardella, Matthew

edit: As pointed out by @michael.hor257k it assumed the XML will not have any mixed content


As Martin Honnen pointed out in his deleted answer, in XSLT 2.0 this could be accomplished by a single xsl:value-of instruction. Here's his answer, with a minor correction by me:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
    <xsl:value-of select="//*[not(@drop) and text()]" separator=" "/>
</xsl:template>

</xsl:stylesheet>

However, this assumes no mixed content in the source XML (as I believe the other answers do too). If this were a requirement, you could use :

<xsl:value-of select="string-join(//*[not(@drop)]/text(), ' ')" />

instead.

Tags xslt

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK