6

I can't figure out how to access all the attributes in a tag from an XML document.

Let's say I have the following XML:

<names>
  <name firstname="Rocky" lastname="Balboa" divider=", "/>
  <name firstname="Ivan" lastname="Drago" divider=", "/>
</names>

I want the following output: Rocky Balboa, Ivan Drago,

What I currently have is:

<xsl:for-each select="names/name">
   <xsl:value-of select="@firstname"/>
   <xsl:value-of select="@lastname"/>
   <xsl:value-of select="@divider"/>
</xsl:for-each>

What I'm wondering is if it's possible to do this in just one value-of select instead of having to do three of them. So to clarify, I want to be able to output all the attributes in the tag with one single value-of select. Is this possible?

Thanks.

6
  • You can use this XPath @* to get all attributes, e.g.: <br/> <xsl:template match="/*"> <xsl:for-each select="@*"> <xsl:value-of select="concat(name(), ': ', ., ' ')"/> </xsl:for-each> </xsl:template> Commented May 15, 2013 at 15:53
  • please consider the fromatting. Due to strange reasons formatting is not working on my end. Commented May 15, 2013 at 15:54
  • Alright I guess you could do that aswell. But I want to figure out how/if this is possible to do it in the way I have, but with just one value-of select. Commented May 15, 2013 at 15:56
  • That is what I mentioned. If you refer to above example @* use you will see it will require just one value-of select and you will be good. I hope this helps. I am re-posting my comment with better indentation and formatting below. Hoe that will help. Commented May 15, 2013 at 16:44
  • How would you like to handle blanks. This is not even reasonable in your current solution. (You are generation RockyBalboa, IvanDrago, .) Commented May 15, 2013 at 16:46

5 Answers 5

7

try the following:

<xsl:template match="/">
 <xsl:for-each select="names/name/@*">
        <xsl:value-of select="concat( ., ' ')"/>
  </xsl:for-each>
</xsl:template>     
Sign up to request clarification or add additional context in comments.

1 Comment

Lolz - upvoting an answer about XSLT in 2019 - this works great tho!
2

Because I'm not sure if the use of xsl:value-ofis a hard requirement, perhaps something like the following could be what you are locking for.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:template match="name" mode ="print" >
        <xsl:value-of select="@firstname"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="@lastname"/>
        <xsl:value-of select="@divider"/>
    </xsl:template>

    <xsl:template match="/">
        <xsl:apply-templates  select="names/name" mode="print"/>
    </xsl:template>

</xsl:stylesheet>

You can use <xsl:apply-templates select="names/name" mode="print"/> at any position you have considered about using a one line value-of for all attributes.
The above template will generate the following output:

Rocky Balboa, Ivan Drago,

Update crate output without using the attribute names:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:template match="name" mode ="print" >
        <xsl:for-each select="@*" >
            <xsl:if test="not(position() = last() or position() = 1)">
                <xsl:text> </xsl:text>
            </xsl:if>
            <xsl:value-of select="."/>

        </xsl:for-each>
    </xsl:template>

    <xsl:template match="/">
        <xsl:apply-templates  select="names/name" mode="print"/>
    </xsl:template>

</xsl:stylesheet>

Comments

1

You can use this XPath @* to get all attributes, e.g.:

<xsl:template match="/*">
    <xsl:for-each select="@*">
        <xsl:value-of select="concat(name(), ': ', ., ' ')"/>
    </xsl:for-each>
</xsl:template>

This will let you use just one value-of select to get the output you want. It will take all attribute into consideration.

This should be a sufficient hint for you to figure out things. Let me know if you have any other question.

1 Comment

This has not much to do with the request. You are generating something like firstname: Ivan lastname:... (if any). But requested is: Rocky Balboa, Ivan Drago,
0

If you can use XSLT 2.0, you can do something like this:

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

    <xsl:template match="text()"/>

    <xsl:template match="*[@*]">
        <xsl:value-of select="@*[not(name()='divider')]" separator=" "/>
        <xsl:value-of select="@divider"/>           
        <xsl:apply-templates/>
    </xsl:template>

</xsl:stylesheet>

This will output all attributes and you have no control over the order, so if you want to specify an order, you can either use a sequence:

<xsl:value-of select="(@firstname,@lastname)" separator=" "/>

or do an xsl:apply-templates with an xsl:sort to sort the attributes by name() (or whatever). Let me know if you'd like an example.

2 Comments

I must have explained myself wrong. I'm wondering if its possible to print out all the attributes, not but calling the names of the attributes. Something like value-of select "*" or along those lines.
@ErikÅstrand - That's what <xsl:value-of select="@*[not(name()='divider')]" separator=" "/> does except that it ignores the divider attribute. You could also do <xsl:value-of select="@*" separator=" "/>, but you wouldn't be guaranteed that divider would be the last output.
0

The following works in XSLT 2.0:

<xsl:for-each select="names/name">
   <xsl:value-of select="@firstname, @lastname, @divider"/>
</xsl:for-each>

and in 3.0 you can do:

<xsl:value-of select="names/name!(@firstname, @lastname, @divider)"/>

though you may need to make adjustments to get the whitespace the way you want it.

1 Comment

Hey. Thanks for the reply. I'm not acually wondering how to print out all the attributes in one line by calling the acual names of the attributes. I'm looking for a way to simply call all the attributes, regardless of the names. Something along these lines: value-of select = " * ". Something that can print all the attributes, but not by calling them individually.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.