XSLT: если тег существует, примените шаблон; если нет, выберите статическое значение

#xml #xslt #xslt-2.0 #xslt-1.0

#xml #xslt #xslt-2.0 #xslt-1.0

Вопрос:

Я новичок в XSLT в целом, поэтому, пожалуйста, потерпите меня…

Имея это в виду, то, что я пытаюсь сделать, это проверить наличие определенного тега в XML. Если он есть, я хочу применить шаблон. Если нет, я хочу добавить его (как пустое значение). В основном всегда заставляя его быть в конечном выводе. Как бы мне это сделать?

У меня было что-то вроде этого…

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

Верхняя часть кода — это то, что я считаю неправильным. Нужно что-то в otherwise теге, и я думаю, что моя when часть неверна.

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

Кто-нибудь может помочь? Заранее благодарю вас.

Редактировать:

Да, в конце концов, мне нужен, по крайней мере, <country /> тег, который должен быть в XML. Но возможно, что он не существует вообще. Если он не существует, я должен его вставить. Примером хорошего ввода было бы <country>US</country>

Комментарии:

1. Рассмотрите возможность публикации двух входных образцов (один с присутствующими данными, другой с отсутствующими данными), затем покажите нам выходные данные, которые вы хотите создать для обоих. Тогда мы можем помочь с правильным XSLT. Боюсь, ваше текущее описание «проверка на наличие определенного тега» не очень точное, и трудно сказать, <xsl:when test="@href"> соответствует ли оно вашим требованиям. Это проверит, имеет ли контекстный узел href атрибут, тогда как проверка на наличие «тега» звучит так, что вы хотите проверить определенный элемент node. В вашем otherwise вы просто можете захотеть поместить <country>foo</country> результат el

2. ‘<xsl:when test=»@href»>’, я полагаю, неверно

3. Хороший вопрос, 1. Смотрите мой ответ для еще более короткого и простого решения, чем принятое в настоящее время. В моем решении абсолютно отсутствуют условные инструкции XSLT!

Ответ №1:

В шаблоне для родительского элемента ожидается, что элемент country будет использоваться, например

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

Вместо foo используйте имя родительского элемента. И, конечно, вы могли бы также выполнить другие действия, такие как копирование элемента, я сосредоточился на if проверке. На самом деле вам не нужно, xsl:choose/when/otherwise на мой взгляд, xsl:if должно быть достаточно, поскольку apply-templates ничего не будут делать с дочерними элементами, которые не существуют.

Комментарии:

1. я сделал кое-что очень similar….so я думаю, вы получили правильный ответ. для этого было важно время, поэтому я использовал его, пока оно не было правильным. но спасибо в любом случае.

2. Что, если бы я хотел посмотреть, не существует ли он, или пустой, если он существует?

3. @SearchForKnowledge, подумайте о том, чтобы задать новый отдельный вопрос с необходимыми деталями ввода XML и желаемого результата.

Ответ №2:

Еще проще:

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

Обратите внимание:

Никакие условные инструкции XSLT (такие как <xsl:if> ) не используются и в них нет необходимости.

Очень часто наличие <xsl:if> или <xsl:choose> указывает на то, что код можно переработать и значительно улучшить, среди прочего, избавившись от условных инструкций.

Комментарии:

1. Но что бы вы сделали, если бы вам понадобилось предоставить другой элемент по умолчанию? например, <город>.

2. @JRQ, в данном конкретном случае не предоставлен конкретный исходный XML-документ, поэтому можно только догадываться о желаемой схеме. Скажите: ` <страна> США</country> <город> Вашингтон</city> ` Или, это может быть (возможности бесконечны): ` <название страны=»US»> <город> Вашингтон</city> </country> `

3. Я это вижу. Но более общее решение было бы лучше, чем то, которое больше не работает, когда количество тестов больше одного.

4. @JRQ, согласен. Вот почему любой может задать новый вопрос с более конкретным сценарием, который его интересует.

Ответ №3:

Вам даже не нужна какая-либо условная обработка. Эта таблица стилей:

 <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>
  

С помощью этого ввода:

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

Вывод:

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