我正在使用XSLT 1.0将XML文档转换为不同的XML架构。源文档可能有也可能没有元素,具体取决于它从中构建的源数据库。
EG
<Patients>
<Patient id="1019">
<Surname>Acqua</Surname>
<Forenames>Matthew James</Forenames>
<VoicePhone>0111 222 33333</VoicePhone>
</Patient>
<Patient id="1020">
<Surname>Red</Surname>
<Forenames>James Alan</Forenames>
</Patient>
</Patients>
通过 XML 转换后生成的输出将包含空元素,因为第二个患者中的 VoicePhone 不存在(而不是存在而是空的(。
XSLT 遵循以下行:
<xsl:template match="//Patients/Patient">
<PatientRxs>
<PatientInfo>
<FirstName>
<xsl:value-of select="Forenames"/>
</FirstName>
<Telephone>
<xsl:value-of select="VoicePhone"/>
</Telephone>
</PatientInfo>
</PatientRxs>
</xsl:template>
我最终得到:
<PatientRxs>
<PatientInfo>
<FirstName>Matthew James</FirstName>
<Telephone>0111 222 33333</Telephone>
</PatientInfo>
</PatientRxs>
<PatientRxs>
<PatientInfo>
<FirstName>James Alan</FirstName>
<Telephone/>
</PatientInfo>
</PatientRxs>
我真正想要的地方:
<PatientRxs>
<PatientInfo>
<FirstName>Matthew James</FirstName>
<Telephone>0111 222 33333</Telephone>
</PatientInfo>
</PatientRxs>
<PatientRxs>
<PatientInfo>
<FirstName>James Alan</FirstName>
</PatientInfo>
</PatientRxs>
尽管我可以测试该值是否存在,但这只是源文档中可能不存在的数百个元素中的 1 个,并且希望避免让 XSLT 工作表测试其中的每一个
尝试使用与任何元素匹配的通用模板,但采用参数以允许重命名该元素
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="//Patients/Patient">
<PatientRxs>
<PatientInfo>
<xsl:apply-templates select="Forenames" mode="field">
<xsl:with-param name="newName" select="'FirstName'" />
</xsl:apply-templates>
<xsl:apply-templates select="VoicePhone" mode="field">
<xsl:with-param name="newName" select="'Telephone'" />
</xsl:apply-templates>
</PatientInfo>
</PatientRxs>
</xsl:template>
<xsl:template match="*" mode="field">
<xsl:param name="newName" select="local-name()" />
<xsl:element name="{$newName}">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
因此,如果匹配的元素不存在,则根本不会获得该元素的输出。
<xsl:template match="Patients">
<xsl:element name="PatientRxs">
<xsl:for-each select="Patient">
<xsl:element name="PatientInfo">
<xsl:element name="Forenames">
<xsl:value-of select="Forenames"/>
</xsl:element>
<xsl:if test="VoicePhone">
<xsl:element name="Telephone">
<xsl:value-of select="VoicePhone"/>
</xsl:element>
</xsl:if>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
Test if Voicephone exist then insert element otherwise not.
<xsl:template match="Patients">
<xsl:element name="PatientRxs">
<xsl:for-each select="Patient">
<xsl:element name="PatientInfo">
<xsl:element name="Forenames">
<xsl:value-of select="Forenames"/>
</xsl:element>
<xsl:apply-templates select="VoicePhone"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template match="VoicePhone">
<xsl:choose>
<xsl:when test="text()">
<xsl:element name="Telephone">
<xsl:value-of select="."/>
</xsl:element>
</xsl:when>
<xsl:when test="empty(.)"/>
</xsl:choose>
</xsl:template>
试试这个