Reputation: 335
I'm trying to build a transformation that will:
For example, if "Age" is not provided for a person then it should be defaulted to "Unknown" in the node following the required "Name" node:
<People>
<Person>
<Name>Bob Smith</Name>
<Age>34</Age>
<Gender>Male></Gender>
</Person>
<Person>
<Name>Jane Smith</Name>
<Gender>Female</Gender>
</Person>
</People>
Becomes:
<People>
<Person>
<Name>Bob Smith</Name>
<Age>34</Age>
<Gender>Male></Gender>
</Person>
<Person>
<Name>Jane Smith</Name>
<Age>Unknown</Age>
<Gender>Female</Gender>
</Person>
</People>
I have the following XSLT, which correctly adds the default, but it adds the default to the end of the Person section. I need the node to be added just after the Name node:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:p="http://services.ic.gov.uk/common-person/v1.0">
<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="Person[not(Age)]">
<Person>
<xsl:apply-templates select="node()|@*" />
<Age>Unknown</Age>
</Person>
</xsl:template>
</xsl:stylesheet>
Could anyone help me implement the additional requirement for the "Age" node to be added after the 'Name" node?
Many thanks!
Upvotes: 1
Views: 1978
Reputation: 122414
If you know there will always be a Name
then the simplest approach would be to move the logic into a Name
template:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:p="http://services.ic.gov.uk/common-person/v1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*" name="ident">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="Name[not(../Age)]">
<!-- copy the Name as usual -->
<xsl:call-template name="ident" />
<!-- and add Age immediately after it -->
<Age>Unknown</Age>
</xsl:template>
</xsl:stylesheet>
If a Person
can have more than one Name
you may need to make the match more specific, e.g. Name[last()][not(../Age)]
to add the Age
after the last occurrence of Name
within the Person
rather than after every one.
Upvotes: 3