am trying to flatten an XML element based on a child element name using XSLT 1.0
The source XML:
<Contact>
<ContactPurpose>
<PurposeAsPlainText xmlns="cds_dt">Call</PurposeAsPlainText>
</ContactPurpose>
<ContactPurpose>
<PurposeAsEnum xmlns="cds_dt">Call</PurposeAsEnum>
</ContactPurpose>
</Contact>
Should be transformed into the following XML:
<Contact>
<ContactPurpose>O</ContactPurpose>
<ContactPurpose>Call</ContactPurpose>
</Contact>
The Logic is:
IF the child element name is “PurposeAsPlainText “ THEN set “O” for Other in destination
ELSEIF the child element name is “PurposeAsEnum” THEN copy the source value to destination
EDIT 1 : I could be more clear as none of the solutions flattened the xml, please see revised source and dest XML.
EDIT 2 : Here is the XML I was testing against. The two tranform solutions below actually do work on my original xml but not the revised xml that I was testing using .NET 4.0 XslCompiledTransform. Or should I make a new question?
<MyDS xmlns="cds" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PatientRecord>
<Demographics>
<Contact>
<ContactPurpose>
<PurposeAsPlainText xmlns="cds_dt">Call</PurposeAsPlainText>
</ContactPurpose>
<ContactPurpose>
<PurposeAsEnum xmlns="cds_dt">Call</PurposeAsEnum>
</ContactPurpose>
</Contact>
</Demographics>
</PatientRecord>
</MyDS>
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cds="cds_dt" exclude-result-prefixes="cds">
<!-- identity transform - just copy things that don't have a better rule -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!- a rule for what needs changing -->
<xsl:template match="ContactPurpose[cds:PurposeAsPlainText] ">
<ContactPurpose>O</ContactPurpose>
</xsl:template>
</xsl:stylesheet>
Update: modified the answer to fit the changed XML source document.
The description is not very clear, but here's what I think you're trying to do:
<xsl:stylesheet version="1.0" xmlns:cds_dt="cds_dt" xmlns:cds="cds"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Identity transform -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cds:ContactPurpose">
<xsl:copy>
<xsl:choose>
<!-- when there is a child element PurposeAsPlainText
in the cds_dt namespace: -->
<xsl:when test="cds_dt:PurposeAsPlainText">0</xsl:when>
<!-- I'm guessing that PurposeAsEnum is also supposed to be
in the cds_dt namespace. -->
<xsl:otherwise>
<xsl:value-of select="cds_dt:PurposeAsEnum" />
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This can be done in a simple and short way (no explicit conditionals) :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="cds_dt" exclude-result-prefixes="x">
<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="ContactPurpose/x:PurposeAsPlainText/text()">0</xsl:template>
<xsl:template match="ContactPurpose/*"><xsl:apply-templates/></xsl:template>
</xsl:stylesheet>
when applied to the following XML document (extended to encorporate both cases of interest):
<Contact>
<ContactPurpose>
<PurposeAsPlainText xmlns="cds_dt">Call</PurposeAsPlainText>
</ContactPurpose>
<ContactPurpose>
<PurposeAsEnum xmlns="cds_dt">Call</PurposeAsEnum>
</ContactPurpose>
</Contact>
produces the wanted, correct result :
<Contact>
<ContactPurpose>0</ContactPurpose>
<ContactPurpose>Call</ContactPurpose>
</Contact>
Explanation :
Overriding the identity rule and appropriate use of templates/match patterns.
Update : The OP has modified his XML document, which is now in a default namespace:
<MyDS xmlns="cds" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PatientRecord>
<Demographics>
<Contact>
<ContactPurpose>
<PurposeAsPlainText xmlns="cds_dt">Call</PurposeAsPlainText>
</ContactPurpose>
<ContactPurpose>
<PurposeAsEnum xmlns="cds_dt">Call</PurposeAsEnum>
</ContactPurpose>
</Contact>
</Demographics>
</PatientRecord>
</MyDS>
Accordingly, here is a slightly modified transformation that produces the wanted result :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="cds_dt" xmlns:c="cds" exclude-result-prefixes="c x">
<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="c:ContactPurpose/x:PurposeAsPlainText/text()">0</xsl:template>
<xsl:template match="c:ContactPurpose/*"><xsl:apply-templates/></xsl:template>
</xsl:stylesheet>
When this transformation is applied on the new XML document (closest above), the new wanted, correct result is produced :
<MyDS xmlns="cds" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PatientRecord>
<Demographics>
<Contact>
<ContactPurpose>0</ContactPurpose>
<ContactPurpose>Call</ContactPurpose>
</Contact>
</Demographics>
</PatientRecord>
</MyDS>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.