How to Modify XSLT to Reorder XML Elements Based on Specific Criteria?
Questions about XML that are not covered by the other forums should go here.
-
- Posts: 1
- Joined: Fri Jul 12, 2024 9:28 am
- Contact:
How to Modify XSLT to Reorder XML Elements Based on Specific Criteria?
I'm working on an XML transformation project and need some help with XSLT. I have an XML file with multiple <Student> elements, each containing <HUSID>, <SURNAME>, <NUMHUS>, and <COURSEID> elements. My goal is to reorder the <COURSEID> elements within each <Student> element so that all <COURSEID> values are nested within a single <InstancePeriod> element.
Here's a simplified version of my XML:
And here's the XSLT I'm currently using:
The output I'm getting is:
But what I want is:
Could anyone help me adjust my XSLT to achieve the desired output? Any tips or suggestions would be greatly appreciated!
Here's a simplified version of my XML:
Code: Select all
<dataroot>
<Student>
<HUSID>idno</HUSID>
<SURNAME>Second Name</SURNAME>
<NUMHUS>idno2</NUMHUS>
<COURSEID>course1</COURSEID>
</Student>
<Student>
<HUSID>idno</HUSID>
<SURNAME>Surname</SURNAME>
<NUMHUS>idno2</NUMHUS>
<COURSEID>course2</COURSEID>
</Student>
<Student>
<HUSID>idno</HUSID>
<SURNAME>Surname</SURNAME>
<NUMHUS>idno2</NUMHUS>
<COURSEID>course3</COURSEID>
</Student>
</dataroot>
Code: Select all
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="dataroot">
<dataroot>
<xsl:apply-templates select="Student[not(HUSID = preceding-sibling::Student/HUSID)]" mode="student"/>
</dataroot>
</xsl:template>
<xsl:template match="Student" mode="student">
<xsl:variable name="husid" select="HUSID"/>
<xsl:variable name="surname" select="SURNAME"/>
<Student>
<HUSID><xsl:value-of select="$husid"/></HUSID>
<SURNAME><xsl:value-of select="$surname"/></SURNAME>
<xsl:apply-templates select="/dataroot/Student[HUSID/text()=$husid]" mode="instanceperiod"/>
</Student>
</xsl:template>
<xsl:template match="Student" mode="instanceperiod">
<xsl:variable name="courseid" select="COURSEID"/>
<Instance>
<NUMHUS><xsl:value-of select="NUMHUS"/></NUMHUS>
<InstancePeriod>
<COURSEID><xsl:value-of select="$courseid"/></COURSEID>
</InstancePeriod>
</Instance>
</xsl:template>
</xsl:stylesheet>
Code: Select all
<dataroot>
<Student>
<HUSID>idno</HUSID>
<SURNAME>Second Name</SURNAME>
<Instance>
<NUMHUS>idno2</NUMHUS>
<InstancePeriod>
<COURSEID>course1</COURSEID>
</InstancePeriod>
</Instance>
<Instance>
<NUMHUS>idno2</NUMHUS>
<InstancePeriod>
<COURSEID>course2</COURSEID>
</InstancePeriod>
</Instance>
<Instance>
<NUMHUS>idno2</NUMHUS>
<InstancePeriod>
<COURSEID>course3</COURSEID>
</InstancePeriod>
</Instance>
</Student>
</dataroot>
Code: Select all
<dataroot>
<Student>
<HUSID>idno</HUSID>
<SURNAME>Second Name</SURNAME>
<Instance>
<NUMHUS>idno2</NUMHUS>
<InstancePeriod>
<COURSEID>course1</COURSEID>
<COURSEID>course2</COURSEID>
<COURSEID>course3</COURSEID>
</InstancePeriod>
</Instance>
</Student>
</dataroot>
-
- Posts: 390
- Joined: Thu Jul 01, 2004 12:29 pm
Re: How to Modify XSLT to Reorder XML Elements Based on Specific Criteria?
Hello,
To achieve your desired output, you need to adjust your XSLT to ensure that all `<COURSEID>` elements are nested within a single `<InstancePeriod>` element for each `<Student>`. Here’s how you can modify your XSLT to achieve that:
1. First, collect all `<COURSEID>` elements for each `<Student>` and then wrap them inside a single `<InstancePeriod>` element.
2. Modify the templates to ensure that the correct structure is maintained.
Here's the adjusted XSLT:
In this adjusted XSLT:
- The `Student` template in `student` mode collects `<HUSID>` and `<SURNAME>` and constructs the `<Instance>` and `<InstancePeriod>` elements.
- The `Student` template in `courseid` mode only outputs `<COURSEID>` elements, which are then nested within the single `<InstancePeriod>` element created in the previous template.
I recommend trying the "Chat About Code" feature from the "Oxygen AI Positron" plugin. If you pose the same question in the chat, when you are in an XSLT document, you will receive a similar result as the one I posted. Afterwards, you can refine this result.
For more information, visit: https://www.oxygenxml.com/ai_positron/w ... ed_Actions
Best Regards,
Octavian
To achieve your desired output, you need to adjust your XSLT to ensure that all `<COURSEID>` elements are nested within a single `<InstancePeriod>` element for each `<Student>`. Here’s how you can modify your XSLT to achieve that:
1. First, collect all `<COURSEID>` elements for each `<Student>` and then wrap them inside a single `<InstancePeriod>` element.
2. Modify the templates to ensure that the correct structure is maintained.
Here's the adjusted XSLT:
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="dataroot">
<dataroot>
<xsl:apply-templates select="Student[not(HUSID = preceding-sibling::Student/HUSID)]" mode="student"/>
</dataroot>
</xsl:template>
<xsl:template match="Student" mode="student">
<xsl:variable name="husid" select="HUSID"/>
<xsl:variable name="surname" select="SURNAME"/>
<Student>
<HUSID><xsl:value-of select="$husid"/></HUSID>
<SURNAME><xsl:value-of select="$surname"/></SURNAME>
<Instance>
<NUMHUS><xsl:value-of select="NUMHUS"/></NUMHUS>
<InstancePeriod>
<xsl:apply-templates select="/dataroot/Student[HUSID/text()=$husid]" mode="courseid"/>
</InstancePeriod>
</Instance>
</Student>
</xsl:template>
<xsl:template match="Student" mode="courseid">
<COURSEID><xsl:value-of select="COURSEID"/></COURSEID>
</xsl:template>
</xsl:stylesheet>
- The `Student` template in `student` mode collects `<HUSID>` and `<SURNAME>` and constructs the `<Instance>` and `<InstancePeriod>` elements.
- The `Student` template in `courseid` mode only outputs `<COURSEID>` elements, which are then nested within the single `<InstancePeriod>` element created in the previous template.
I recommend trying the "Chat About Code" feature from the "Oxygen AI Positron" plugin. If you pose the same question in the chat, when you are in an XSLT document, you will receive a similar result as the one I posted. Afterwards, you can refine this result.
For more information, visit: https://www.oxygenxml.com/ai_positron/w ... ed_Actions
Best Regards,
Octavian
Octavian Nadolu
<oXygen/> XML Editor
http://www.oxygenxml.com
<oXygen/> XML Editor
http://www.oxygenxml.com
Return to “General XML Questions”
Jump to
- Oxygen XML Editor/Author/Developer
- ↳ Feature Request
- ↳ Common Problems
- ↳ DITA (Editing and Publishing DITA Content)
- ↳ Artificial Intelligence (AI Positron Assistant add-on)
- ↳ SDK-API, Frameworks - Document Types
- ↳ DocBook
- ↳ TEI
- ↳ XHTML
- ↳ Other Issues
- Oxygen XML Web Author
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Content Fusion
- ↳ Feature Request
- ↳ Common Problems
- Oxygen JSON Editor
- ↳ Feature Request
- ↳ Common Problems
- Oxygen PDF Chemistry
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Feedback
- ↳ Feature Request
- ↳ Common Problems
- Oxygen XML WebHelp
- ↳ Feature Request
- ↳ Common Problems
- XML
- ↳ General XML Questions
- ↳ XSLT and FOP
- ↳ XML Schemas
- ↳ XQuery
- NVDL
- ↳ General NVDL Issues
- ↳ oNVDL Related Issues
- XML Services Market
- ↳ Offer a Service