How to copy a specific attribute using XSLT?

Apologies for the basic nature of these questions - I'm completely new to XSLT (and also to).

I need to convert the following XML returned by the Sharepoint web service:

<GetGroupCollectionFromUser xmlns= "http://schemas.microsoft.com/sharepoint/soap/directory/"> <Groups> <Group ID="3" Name="Group1" Description="Description" OwnerID="1" OwnerIsUser="False" /> <Group ID="15" Name="Group2" Description="Description" OwnerID="12" OwnerIsUser="True" /> <Group ID="16" Name="Group3" Description="Description" OwnerID="7" OwnerIsUser="False" /> </Groups> </GetGroupCollectionFromUser> 

in it:

 <GetGroupCollectionFromUser xmlns= "http://schemas.microsoft.com/sharepoint/soap/directory/"> <Groups> <Group Name="Group1" /> <Group Name="Group2" /> <Group Name="Group3" /> </Groups> </GetGroupCollectionFromUser> 

Basically, I need to drop all attributes for every Group element except Name. After much research and mastering, and in particular, dropping the namespace declaration from the source XML, I came up with what I need almost exactly what I need:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="utf-8" indent="no"/> <xsl:template match="/GetGroupCollectionFromUser"> <xsl:copy> <xsl:apply-templates select="Groups" /> </xsl:copy> </xsl:template> <xsl:template match="Groups"> <xsl:copy> <xsl:apply-templates select="Group" /> </xsl:copy> </xsl:template> <xsl:template match="Group"> <xsl:copy> <xsl:apply-templates select="@Name" /> </xsl:copy> </xsl:template> </xsl:stylesheet> 

However, instead of the Name attribute, the above gives me the value of the Name attribute inserted as text in the Group element, for example:

 <GetGroupCollectionFromUser> <Groups> <Group>Group1</Group> <Group>Group2</Group> <Group>Group3</Group> </Groups> </GetGroupCollectionFromUser> 

Ultimately, this will be consumed by a third-party application expecting an XML-oriented attribute. I'm sure I miss something embarrassing for the obvious, but no matter what I do with it, I can't just insert the Name attribute. Two questions:

How to change XSLT to return the Name attribute for each Group element, instead of its value as text?

And how do I handle the namespace correctly? When I included it in XSLT, having tried several methods based on examples that I found here and elsewhere on the Internet, I get nothing back.

Thanks in advance for any advice.

+7
source share
4 answers

This is perhaps one of the shortest transformations that correctly outputs the desired result :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="@*[not(name()='Name')]"/> </xsl:stylesheet> 

When applied to the provided XML document :

 <GetGroupCollectionFromUser xmlns= "http://schemas.microsoft.com/sharepoint/soap/directory/"> <Groups> <Group ID="3" Name="Group1" Description="Description" OwnerID="1" OwnerIsUser="False" /> <Group ID="15" Name="Group2" Description="Description" OwnerID="12" OwnerIsUser="True" /> <Group ID="16" Name="Group3" Description="Description" OwnerID="7" OwnerIsUser="False" /> </Groups> </GetGroupCollectionFromUser> 

required, the correct result is obtained :

 <GetGroupCollectionFromUser xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/"> <Groups> <Group Name="Group1"/> <Group Name="Group2"/> <Group Name="Group3"/> </Groups> </GetGroupCollectionFromUser> 

Explanation

  • An identity rule (template) copies each node "as-is".

  • There is only one template that overrides the identification rule . It matches any attribute whose name is not "Name". The body of the template is empty, and this leads to the fact that any associated attribute is not copied.

Using and redefining an identity rule is the most fundamental and powerful XSLT design pattern. Read about it here .

+2
source

The way to handle these situations is to override the Identity transform:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msft="http://schemas.microsoft.com/sharepoint/soap/directory/"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <xsl:template match="msft:Group"> <xsl:copy> <xsl:apply-templates select="@Name" /> </xsl:copy> </xsl:template> </xsl:stylesheet> 

Output:

 <GetGroupCollectionFromUser xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/"> <Groups> <Group Name="Group1" /> <Group Name="Group2" /> <Group Name="Group3" /> </Groups> </GetGroupCollectionFromUser> 

Note that the output is correctly placed in the names.

This solution is preferred because of its simplicity and flexibility. All nodes and attributes are copied as is, unless there is an override that defines alternative behavior.

+3
source

I think it will be easier for you if you do not use xsl:copy here. Try the following:

 <xsl:template match="Groups/*"> <xsl:element name="Group"> <xsl:attribute name="Name"> <xsl:value-of select="@Name" /> </xsl:attribute> </xsl:element> </xsl:template> 

The answer to the second question is the FAQ . Declare a namespace and use the declared prefix in xsl. Final decision:

 <xsl:stylesheet version="1.0" xmlns:myns="http://schemas.microsoft.com/sharepoint/soap/director/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="utf-8" indent="no"/> <xsl:template match="/myns:GetGroupCollectionFromUser"> <Groups> <xsl:apply-templates select="myns:Groups" /> </Groups> </xsl:template> <xsl:template match="myns:Groups/*"> <xsl:element name="Group"> <xsl:attribute name="Name"> <xsl:value-of select="@Name" /> </xsl:attribute> </xsl:element> </xsl:template> </xsl:stylesheet> 
+2
source

This seems to work for me:

 <xsl:template match="Group"> <xsl:copy> <xsl:attribute name="Name"> <xsl:apply-templates select="@Name" /> </xsl:attribute> </xsl:copy> </xsl:template> 
0
source

All Articles