使用XSL检查XML中的元素

时间:2012-11-07 09:03:50

标签: xml xslt

所以我想在通过Web服务发送之前使用XSL格式化日期,但是我还想检查如果DOB字段为空,它仍然是空白的,如果它有一个日期,它将会继续格式化日期。

现在我已经有了XSL来格式化日期 - 但是我似乎无法使条件正常工作,如果它是空的,请将其留空

在通过XSL之前的

XML:

<BriefDetails>
    <ObjectID>
        <flt:ObjectType>C1</flt:ObjectType>
    </ObjectID>
</BriefDetails>
<Name>
    <Title>Dr</Title>
    <Forename>Paul</Forename>
    <Surname>Smith</Surname>
    <flt:Preferred>true</flt:Preferred>
</Name>
<ContactEmails>
    <EmailAddress>mail@mail.com</EmailAddress>
    <flt:Preferred>true</flt:Preferred>
</ContactEmails>
<DateOfBirth />
<ContactPostals>
    <AddressNumber>34</AddressNumber>
    <AddressLine>Hopeless Road</AddressLine>
    <AddressLine>Maghera</AddressLine>
    <Postcode>BT74 2TY</Postcode>
    <flt:Preferred>true</flt:Preferred>
</ContactPostals>
<ContactPhones>
    <Number>5545454</Number>
    <flt:Preferred>false</flt:Preferred>
</ContactPhones>
<ContactPhones>
    <Number>5454545</Number>
    <flt:Preferred>false</flt:Preferred>
</ContactPhones>

XSL之后的XML:

<BriefDetails>
    <ObjectID>
        <flt:ObjectType>C1</flt:ObjectType>
    </ObjectID>
</BriefDetails>
<Name>
    <Title>Dr</Title>
    <Forename>Paul</Forename>
    <Surname>Smith</Surname>
    <flt:Preferred>true</flt:Preferred>
</Name>
<ContactEmails>
    <EmailAddress>mail@mail.com</EmailAddress>
    <flt:Preferred>true</flt:Preferred>
</ContactEmails>
***<DateOfBirth>--</DateOfBirth>***
<ContactPostals>
    <AddressNumber>34</AddressNumber>
    <AddressLine>Hopeless Road</AddressLine>
    <AddressLine>Maghera</AddressLine>
    <Postcode>BT74 2TY</Postcode>
    <flt:Preferred>true</flt:Preferred>
</ContactPostals>
<ContactPhones>
    <Number>5545454</Number>
    <flt:Preferred>false</flt:Preferred>
</ContactPhones>
<ContactPhones>
    <Number>5454545</Number>
    <flt:Preferred>false</flt:Preferred>
</ContactPhones>

上面你会看到DOB为 -

正在使用XSL:

<xsl:template match="DateOfBirth">
    <xsl:element name="DateOfBirth">
        <xsl:call-template name="formatDate">
            <xsl:with-param name="dateParam" select="." />
        </xsl:call-template>
    </xsl:element>
</xsl:template>

<xsl:template name="formatDate">
    <xsl:param name="dateParam" />
    <!-- input format mm/dd/yyyy or m/d/yyyy -->
    <!-- output format yyyy-mm-dd -->

    <!-- parse out the day, month and year -->
    <xsl:variable name="day">
        <xsl:value-of select="substring-before($dateParam,'/')" />
    </xsl:variable>
    <xsl:variable name="month">
        <xsl:value-of select="substring-before(substring-after($dateParam,'/'),'/')" />
    </xsl:variable>
    <xsl:variable name="year">
        <xsl:value-of select="substring-after(substring-after($dateParam,'/'),'/')" />
    </xsl:variable>

    <!-- now print them out. Pad with 0 where necessary. -->
    <xsl:value-of select="$year" />
    <xsl:value-of select="'-'" />
    <xsl:if test="string-length($month) = 1">
        <xsl:value-of select="'0'" />
    </xsl:if>
    <xsl:value-of select="$month" />
    <xsl:value-of select="'-'" />
    <xsl:if test="string-length($day) = 1">
        <xsl:value-of select="'0'" />
    </xsl:if>
    <xsl:value-of select="$day" />
</xsl:template>

我尝试添加一个条件:

<xsl:template match="DateOfBirth">
    <xsl:for-each select="DateOfBirth">
        <xsl:if test="string-length(DateOfBirth) != 0">
            <xsl:call-template name="formatDate">
                <xsl:with-param name="dateParam" select="DateOfBirth" />
            </xsl:call-template>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

<xsl:template name="formatDate">
    <xsl:param name="dateParam" />
    <!-- input format mm/dd/yyyy or m/d/yyyy -->
    <!-- output format yyyy-mm-dd -->

    <!-- parse out the day, month and year -->
    <xsl:variable name="day">
        <xsl:value-of select="substring-before($dateParam,'/')" />
    </xsl:variable>
    <xsl:variable name="month">
        <xsl:value-of select="substring-before(substring-after($dateParam,'/'),'/')" />
    </xsl:variable>
    <xsl:variable name="year">
        <xsl:value-of select="substring-after(substring-after($dateParam,'/'),'/')" />
    </xsl:variable>

    <!-- now print them out. Pad with 0 where necessary. -->
    <xsl:value-of select="$year" />
    <xsl:value-of select="'-'" />
    <xsl:if test="string-length($month) = 1">
        <xsl:value-of select="'0'" />
    </xsl:if>
    <xsl:value-of select="$month" />
    <xsl:value-of select="'-'" />
    <xsl:if test="string-length($day) = 1">
        <xsl:value-of select="'0'" />
    </xsl:if>
    <xsl:value-of select="$day" />
</xsl:template>

但是这现在剥离了XML中的DOB

关于如何实现这一目标的任何建议?

1 个答案:

答案 0 :(得分:2)

问题在于您的IF条件

<xsl:if test="string-length(DateOfBirth) != 0">

此时您已经定位在 DateOfBirth 元素上,因此这实际上是在当前元素中查找名为 DateOfBirth 的子元素,而不是当前元素本身。

<xsl:if test="string-length(.) != 0">

实际上,您似乎也添加了不必要的 xsl:for-each 。你的模板应该看起来像这样

<xsl:template match="DateOfBirth">
    <DateOfBirth>
        <xsl:if test="string-length(.) != 0">
            <xsl:call-template name="formatDate">
                <xsl:with-param name="dateParam" select="." />
            </xsl:call-template>
        </xsl:if>
    </DateOfBirth>
</xsl:template>

作为旁注,不需要使用 xsl:element 作为静态元素名称,只需直接写出元素。

事实上,还有另一种方法可以在不需要 xsl:if 的情况下完成此操作。您可以在模板匹配中使用条件

<xsl:template match="DateOfBirth[string-length(.) != 0]">
    <DateOfBirth>
        <xsl:call-template name="formatDate">
             <xsl:with-param name="dateParam" select="." />
        </xsl:call-template>
    </DateOfBirth>
</xsl:template>

<xsl:template match="DateOfBirth">
    <DateOfBirth />
</xsl:template>

XSLT也会首先匹配更具体的模板,因此第二个模板只有在 DateOfBirth 为空时才会匹配。此外,如果您在XSLT中使用身份转换,则根本不需要第二个模板。