Как переопределить значения в XML с помощью xsl - PullRequest
1 голос
/ 25 июля 2011

У меня есть XML-файл, как показано ниже.

<rule>  
<ruleType>IC</ruleType>
    <attributes>
        <attribute>
            <attributeName>salience</attributeName>
            <value>5</value>
        </attribute>


     <attribute>
        <attributeName>abc</attributeName>
        <value>123</value>
    </attribute>
    </attributes>
</rule>

Мне нужно изменить значение значимости на основе ruleType.

Например, если ruleType (<ruleType>IC</ruleType>) - IC, тогда мне нужно сгенерировать xml, как показано ниже.

<rule>  
<ruleType>IC</ruleType>
    <attributes>
        <attribute>
            <attributeName>salience</attributeName>
            <value>100</value>
        </attribute>

     <attribute>
        <attributeName>abc</attributeName>
        <value>123</value>
    </attribute>
    </attributes>
</rule>

если типом правила является GC (<ruleType>GC</ruleType>), тогда мне нужно сгенерировать, как показано ниже.

<rule>  
<ruleType>GC</ruleType>
    <attributes>
        <attribute>
            <attributeName>salience</attributeName>
            <value>50</value>
        </attribute>

     <attribute>
        <attributeName>abc</attributeName>
        <value>123</value>
    </attribute>

    </attributes>
</rule>

и иногда я могу получить ruleType как пустой в этом случае, мне нужно сгенерировать, как показано ниже.

<rule>  
<ruleType/>
    <attributes>
        <attribute>
            <attributeName>salience</attributeName>
            <value>10</value>
        </attribute>

     <attribute>
        <attributeName>abc</attributeName>
        <value>123</value>
    </attribute>
    </attributes>
</rule>

Даже если он получает пустые атрибуты, мне также нужно сгенерировать, как указано выше, с некоторым значением по умолчанию, равным 10.

Мне нужно изменить только элементы значения, связанные атрибутом attributeName (значимость). Если значение attributeName отличается от значимого, мне нужно указать его в полученном xml.

Я использую xsl 1.0.

Пожалуйста, дайте мне несколько советов, чтобы сделать то же самое.

1 Ответ

1 голос
/ 25 июля 2011

Ключом к вашей задаче является использование хорошо известного Identity Transformation и переопределение требуемых узлов при необходимости.


[XSLT 2.0] Вы можете использовать новую конструкцию XPath 2.0 if и возможность XSLT 2.0 определять пользовательские функции, минимизируя код до двух легко читаемых шаблонов.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:empo="http://stackoverflow.com/users/253811/empo"
    exclude-result-prefixes="empo">
    <xsl:output indent="yes"/>

    <xsl:function name="empo:default" as="item()">
        <xsl:param name="default"/>
        <attributes>
            <attribute>
                <attributeName>salience</attributeName>
                <value><xsl:value-of select="$default"/></value>
            </attribute>
        </attributes>
    </xsl:function>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="value[preceding-sibling::attributeName='salience']">
        <xsl:variable name="vRT" select="preceding::ruleType[1]"/>
        <xsl:copy>
            <xsl:value-of select="if ($vRT='IC') then 100
                else if ($vRT='GC') then 50
                else 10"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="attributes[count(attribute)=0]">
        <xsl:variable name="vRT" select="preceding-sibling::ruleType[1]"/>
        <xsl:copy-of select="if ($vRT='IC') then empo:default(100)
            else if ($vRT='GC') then empo:default(50)
            else empo:default(10)"/>
    </xsl:template>

</xsl:stylesheet>

[XSLT 1.0] Например, даже если бы вы могли использовать один шаблон на основе инструкции xsl:choose, я бы использовал отдельный шаблон для каждого перезаписываемого значения, в основном для удобства чтения.

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

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="value[preceding::ruleType[1]='IC' 
        and preceding-sibling::attributeName='salience']">
        <xsl:copy>100</xsl:copy>
    </xsl:template>

    <xsl:template match="value[preceding::ruleType[1]='GC'
        and preceding-sibling::attributeName='salience']">
        <xsl:copy>50</xsl:copy>
    </xsl:template>

    <xsl:template match="value[preceding::ruleType[1]=''
        and preceding-sibling::attributeName='salience']">
        <xsl:copy>10</xsl:copy>
    </xsl:template>

    <xsl:template match="attributes[count(attribute)=0 
        and preceding-sibling::ruleType[1]='IC']">
        <attributes>
            <attribute>
                <attributeName>salience</attributeName>
                <value>100</value>
            </attribute>
        </attributes>
    </xsl:template>

    <xsl:template match="attributes[count(attribute)=0 
        and preceding-sibling::ruleType[1]='GC']">
        <attributes>
            <attribute>
                <attributeName>salience</attributeName>
                <value>50</value>
            </attribute>
        </attributes>
    </xsl:template>

    <xsl:template match="attributes[count(attribute)=0 
        and preceding-sibling::ruleType[1]='']">
        <attributes>
            <attribute>
                <attributeName>salience</attributeName>
                <value>10</value>
            </attribute>
        </attributes>
    </xsl:template>

</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...