XSLT: If tag exists, apply template; if not, choos

2020-06-09 06:37发布

问题:

I am new to XSLT in general so please bear with me...

With that in mind, what I am trying to do is check for a certain tag in the XML. If it is there I want to apply a template. If not, I want to add it (as a blank value). Basically always forcing it to be in the final output. How would I do this?

I had something like this...

<xsl:choose>
    <xsl:when test="@href">
        <xsl:apply-templates select="country" />
    </xsl:when>
    <xsl:otherwise>
    </xsl:otherwise>
</xsl:choose>

The top poriton of the code is what I think I have wrong. Need something in the otherwise tag and my when part is wrong i think.

<xsl:template match="country">
    <xsl:if test=". != '' or count(./@*) != 0">
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:template>

Can anyone help? Thank you in advance.

EDIT:

Yes in the end i need at the very least a <country /> tag to be in the XML. But it is possible that it does not exist at all. If it doesn't exist, I have to put it in. An example good input would be <country>US</country>

回答1:

In the template for the parent element the country element is expected to be in use e.g.

<xsl:template match="foo">
  <xsl:if test="not(country)">
    <country>US</country>
  </xsl:if>
  <xsl:apply-templates/>
</xsl:template>

Instead of foo use the name of the parent element. And of course you could also do other stuff like copying the element, I have focused on the if check. You do not really need an xsl:choose/when/otherwise in my view, the xsl:if should suffice as the apply-templates will not do anything with child elements that don't exist.



回答2:

Even simpler:

<xsl:template match="foo[not(country)]">
        <country>US</country>
    <xsl:apply-templates/>
</xsl:template>

Do note:

No XSLT conditional instructions (such as <xsl:if>) are used and they are not necessary.

Very often, the presence of <xsl:if> or <xsl:choose> is an indication that the code can be refactored and significantly improved by, among other things, getting rid of the conditional instructions.



回答3:

You don't even need any kind of Conditional Processing. This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="item[not(country)]">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
            <country>Lilliput</country>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

With this input:

<root>
    <item>
        <country>Brobdingnag</country>
    </item>
    <item>
        <test/>
    </item>
</root>

Output:

<root>
    <item>
        <country>Brobdingnag</country>
    </item>
    <item>
        <test></test>
        <country>Lilliput</country>
    </item>
</root>