Reputation: 126
I have this xml:
<?xml version="1.0" encoding="utf-8"?>
<Document Id="0c744468-67d8-4daa-8ff9-cbd23209c59d" Name="ROW_Easement (1)" TypeId="adde4dc1-0710-452a-82c7-9e5ac1bafe94" TypeName="ROW_Easement" OriginalName="106-19-47A.pdf" MimeType="application/pdf">
<Field Name="File Name" Confidence="1.00" Page="1" Valid="True">106-19-47A</Field>
<Section Name="tblPersonOfInterest">
<SectionCollection Name="From" Count="4">
<Section Name="From 1">
<Field Name="Grantor" Confidence="1.00" Page="1" Valid="True" Location="1.713, 8.200, 6.487, 0.500">MARY E. GIBSON, and husband, E. J. GIBSON;
ROSALIE L. SIEN, and husband, A. C. SIEN, Jr</Field>
</Section>
</SectionCollection>
</Section>
</Document>
I want to replace all the node names with the "Name" attribute value. So far I have:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<ROW_Easement>
<xsl:for-each select="Field">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:value-of select="self::node()" />
</xsl:element>
</xsl:for-each>
<xsl:for-each select="Section">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:value-of select="self::node()" />
</xsl:element>
</xsl:for-each>
<xsl:for-each select="SectionCollection">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:value-of select="self::node()" />
</xsl:element>
</xsl:for-each>
</ROW_Easement>
</xsl:template>
</xsl:stylesheet>
It is resulting in:
<?xml version="1.0" encoding="utf-8"?>
<ROW_Easement>
<File_Name>106-19-47A</File_Name>
<tblPersonOfInterest>
MARY E. GIBSON, and husband, E. J. GIBSON;
ROSALIE L. SIEN, and husband, A. C. SIEN, Jr
</tblPersonOfInterest>
</ROW_Easement>
It's breaking at the SectionCollection node, but I don't see why.
UPDATED per @michael.hor257k's suggestion UPDATE: Using the first suggestion I now get:
<?xml version="1.0" encoding="utf-8"?><ROW_Easement>0c744468-67d8-4daa-8ff9-cbd23209c59dROW_Easement (1)adde4dc1-0710-452a-82c7-9e5ac1bafe94ROW_Easement106-19-47A.pdfapplication/pdf
<File_Name>1.001True106-19-47A</File_Name>
<tblPersonOfInterest>
<From>4
<From_1>
<Grantor>1.001True1.713, 8.200, 6.487, 0.500MARY E. GIBSON, and husband, E. J. GIBSON;
ROSALIE L. SIEN, and husband, A. C. SIEN, Jr</Grantor>
</From_1>
</From>
</tblPersonOfInterest>
</ROW_Easement>
Upvotes: 0
Views: 56
Reputation: 167716
There is no explanation of which attributes you want to keep but based on your sample input and the code you later posted it seems you don't want to keep any attribute but the Name
one on Document
so
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:template match="Document">
<ROW_Easement Name="{@Name}">
<xsl:apply-templates/>
</ROW_Easement>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
might be shorter and avoid the listing of all the attributes you don't want to copy.
Upvotes: 1
Reputation: 126
It may not be the most elegant solution, but using @zx485's answer I changed my XSLT to:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:mode on-no-match="shallow-copy" />
<!-- Remove unnecessary attributes -->
<xsl:template match="@Confidence" />
<xsl:template match="@Id" />
<xsl:template match="@TypeId" />
<xsl:template match="@TypeName" />
<xsl:template match="@OriginalName" />
<xsl:template match="@MimeType" />
<xsl:template match="@Page" />
<xsl:template match="@Valid" />
<xsl:template match="@Count" />
<xsl:template match="@Location" />
<!-- Rename nodes -->
<xsl:template match="Document">
<ROW_Easement>
<xsl:apply-templates select="node()|@*" />
</ROW_Easement>
</xsl:template>
<!-- Copy to new XML -->
<xsl:template match="*">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:apply-templates select="node()|@*[local-name()!='Name']" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
and it now works! Still open to suggestions for ways to improve if anyone wants to give them. Thank you all.
Upvotes: 0
Reputation: 29052
Assuming a well-formed XML input, you can use this simple XSLT-3.0 code. It replaces all element's names with the @Name
attribute and also removes only this attribute from the output. The rest is copied as is by the xsl:mode
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:mode on-no-match="shallow-copy" />
<xsl:template match="Document">
<ROW_Easement>
<xsl:apply-templates select="node()|@*" />
</ROW_Easement>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:apply-templates select="node()|@*[local-name()!='Name']" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Output is:
<?xml version="1.0" encoding="UTF-8"?>
<ROW_Easement Id="0c744468-67d8-4daa-8ff9-cbd23209c59d"
Name="ROW_Easement (1)"
TypeId="adde4dc1-0710-452a-82c7-9e5ac1bafe94"
TypeName="ROW_Easement"
OriginalName="106-19-47A.pdf"
MimeType="application/pdf">
<File_Name Confidence="1.00" Page="1" Valid="True">106-19-47A</File_Name>
<tblPersonOfInterest>
<From Count="4">
<From_1>
<Grantor>
</Grantor>
</From_1>
</From>
</tblPersonOfInterest>
</ROW_Easement>
Upvotes: 1