Как избежать генерации пустых атрибутов в XSLT? - PullRequest
4 голосов
/ 21 апреля 2011

Я написал XSLT-файл со следующим кодом:

<xsl:attribute name="subCode">
    <xsl:value-of select="Field[@key='XY']"/>
</xsl:attribute>

Предположим, что мой INPUT XML выглядит следующим образом:

[...]
<Field key="XY"/>
[...]

В этом случае мой XSLT сгенерирует следующееoutput:

<SomeElement subCode="">
[...]
</SomeElement>

Мой вопрос: как избавиться от пустого атрибута subCode=""?

Я знаю, что это возможно при использовании некоторой условной инструкции, такой как <xsl:if>, однако,это кажется уродливым решением (потому что у меня есть тысячи подобных атрибутов, сгенерированных в моем XSLT).

Это должно быть сделано в том же XSLT.Я не могу добавить постобработку в дополнительный файл XSLT.

Кроме того, для выходного XML определена его схема XSD.И схема говорит, что этот атрибут необязательный .Может быть, есть какой-то способ применить эту XSD-схему для выходного XML?

Заранее спасибо за любую помощь!

Ответы [ 3 ]

4 голосов
/ 21 апреля 2011

Используйте :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
  <someElement>
    <xsl:apply-templates mode="attr"/>
  </someElement>
 </xsl:template>

 <xsl:template match="Field[@key='XY' and not(.='')]" mode="attr">
    <xsl:attribute name="subCode">
      <xsl:value-of select="."/>
    </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к следующему документу XML:

<t>
 <Field key="XY"/>
</t>

требуется, правильный результат (атрибут вообще не генерируется) генерируется :

, когда исходный XML-документ выглядит так:

<t>
 <Field key="XY">1</Field>
</t>

то же преобразование снова производитправильный, требуемый результат;

<someElement subCode="1"/>
1 голос
/ 21 апреля 2011

Вы можете определить шаблон для соответствия атрибуту, который даст вам правильный вывод для пропущенного @key, но если вы также добавите предикат [.!=''], он также должен игнорировать атрибуты без значения.

<xsl:template match="@key[.!='']">
  <xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>

Или в вашем примере, если вы хотите использовать только @key='XY':

<xsl:template match="@key[.='XY']">
  <xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>

Редактировать: Вот более полный пример, который я использовал для проверки этого.

Исходный XML

<Fields>
   <Field key="XY">A</Field>
   <Field key="XY">B</Field>
   <Field key="">C</Field>
   <Field>D</Field>
</Fields>

Сопровождающий XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
  <output>
    <xsl:apply-templates />
  </output>
</xsl:template>

<xsl:template match="Field">
  <xsl:element name="NewField">
    <xsl:apply-templates select="@*"/>
    <xsl:value-of select="."/>
  </xsl:element>
</xsl:template>

<xsl:template match="@key[.='XY']">
  <xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
</xsl:stylesheet>

Результат

<output>
  <NewField subCode="XY">A</NewField>
  <NewField subCode="XY">B</NewField>
  <NewField>C</NewField>
  <NewField>D</NewField>
</output>
0 голосов
/ 21 апреля 2011

Вы должны применить следующие шаблоны к вашим атрибутам:

Этот шаблон соответствует всем ключу атрибутам, значение которых равно 'XY':

<xsl:template match="@key['XY']">
    <xsl:attribute name="subCode">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

Этот шаблонсопоставляет все атрибуты key с (текстовым) значением больше 0:

<xsl:template match="@key[string-length(.)]">
    <xsl:attribute name="other">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

И, наконец, этот шаблон сопоставляет все атрибуты (*), которые являются пустыми:

<xsl:template match="@*[not(string-length(.))]" />

Таким образом, если у вас есть такой ввод, как

<?xml version="1.0"?>
<Root>
    <Field key='v'>One</Field>
    <Field key='XY'>Two</Field>
    <Field key='a'>Three</Field>
    <Field key='v'>Four</Field>
    <Field key='XY'>Five</Field>
    <Field>Six</Field>
    <Field>Seven</Field>
    <Field key='b'>Eight</Field>
    <Field key=''>Nine</Field>
    <Field></Field>
    <Field key='x'>Eleven</Field>
    <Field key=''>Twelve</Field>
    <Field lat='x'>Thirteen</Field>
</Root>

Вы можете сгенерировать вывод:

<?xml version='1.0' ?>
<Root>
    <SomeField other="v">One</SomeField>
    <SomeField subCode="XY">Two</SomeField>
    <SomeField other="a">Three</SomeField>
    <SomeField other="v">Four</SomeField>
    <SomeField subCode="XY">Five</SomeField>
    <SomeField>Six</SomeField>
    <SomeField>Seven</SomeField>
    <SomeField other="b">Eight</SomeField>
    <SomeField>Nine</SomeField>
    <SomeField/>
    <SomeField other="x">Eleven</SomeField>
    <SomeField>Twelve</SomeField>
    <SomeField>xThirteen</SomeField>
</Root>

, используя следующий xslt:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <Root>
            <xsl:apply-templates/>
        </Root>
    </xsl:template>

    <xsl:template match="Field">
        <xsl:element name="SomeField">
            <xsl:apply-templates select="@*"/>
            <xsl:value-of select="text()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@key['XY']">
        <xsl:attribute name="subCode">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@key[string-length(.)]">
        <xsl:attribute name="other">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@key[not(string-length(.))]" />
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...