Xslt根据条件规则引用另一个元素来更改元素值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Xslt根据条件规则引用另一个元素来更改元素值相关的知识,希望对你有一定的参考价值。

我有这样的xml:

<?xml version="1.0" encoding="utf-8"?>
<FormDataRequest>   
  <Name>Bob</Name>
  <sn>Ross</sn>
  <company>MS Paint</company>
  <department>Paint bucket</department>
</FormDataRequest>

我应该根据文本条件改变<company><department>的值。

我试过这个xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
    <xsl:apply-templates select="FormDataRequest" />
</xsl:template>
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>
<xsl:template match="FormDataRequest">
    <xsl:variable name="realcompany">
        <xsl:choose>
            <xsl:when test="./department/text() = 'Paint bucket'">
                <xsl:text>Co company 1</xsl:text>
            </xsl:when>
            <xsl:when test="./department/text() = 'Paint brush'">
                <xsl:text>Co company 2</xsl:text>
            </xsl:when>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="realdepartment">
        <xsl:choose>
            <xsl:when test="./department/text() = 'Paint bucket'">
                <xsl:text>Bucket department</xsl:text>
            </xsl:when>
            <xsl:when test="./department/text() = '´Paint brush'">
                <xsl:text>Brush department</xsl:text>
            </xsl:when>             
        </xsl:choose>
    </xsl:variable>
    <FormDataRequest>
        <xsl:apply-templates select="@*|node()" />
        <company>
            <xsl:value-of select="$realcompany"/>
        </company>
        <department>
            <xsl:value-of select="$realdepartment"/>
        </department>
    </FormDataRequest>
</xsl:template>
</xsl:stylesheet>

输出:

<FormDataRequest>   
  <Name>Bob</Name>
  <sn>Ross</sn>
  <company>MS Paint</company>
  <department>Paint bucket</department>
 <company>Co company 1</company>
 <department>Bucket department</department>
</FormDataRequest>

我不想保留旧公司和部门的价值观。

所以out put应该看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<FormDataRequest>   
  <Name>Bob</Name>
  <sn>Ross</sn>
  <company>Co company 1</company>
  <department>Bucket department</department>
</FormDataRequest>
答案

使用您的XSL代码非常接近,但更容易和可读的方法是创建替换动态模板,这将帮助您更改有关变量条件的公司和部门块值,请参阅下面的XSL:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes"/>
    <!--declare condition for company block-->
    <xsl:variable name="realcompany">
        <xsl:choose>
            <xsl:when test="//department = 'Paint bucket'">
                <xsl:value-of select="'Co company 1'"/>
            </xsl:when>
            <xsl:when test="//department = 'Paint brush'">
                <xsl:value-of select="'Co company 2'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="//company"/>
            </xsl:otherwise>
        </xsl:choose>        
    </xsl:variable>
    <!--declare condition for department block-->
    <xsl:variable name="realdepartment">
        <xsl:choose>
            <xsl:when test="//department = 'Paint bucket'">
                <xsl:value-of select="'Bucket department'"/>
            </xsl:when>
            <xsl:when test="//department = 'Paint brush'">
                <xsl:value-of select="'Brush department'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="//department"/>
            </xsl:otherwise>
        </xsl:choose>         
    </xsl:variable>
    <!--dynamic template for replacing current value to condition value-->    
    <xsl:template name="value-to-replace">
        <xsl:param name="param.str"/>
        <xsl:param name="param.target"/>
        <xsl:param name="param.replacement"/>
        <xsl:choose>
            <xsl:when test="contains($param.str, $param.target)">                    
                <xsl:value-of select="concat(substring-before($param.str, $param.target), $param.replacement, substring-after($param.str, $param.target))"/>              
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$param.str"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!--replace value in company block with realcompany variable condition-->
    <xsl:template match="company[parent::FormDataRequest]">
        <xsl:element name="{name()}">                                    
            <xsl:call-template name="value-to-replace">                       
                <xsl:with-param name="param.str" select="."/>                       
                <xsl:with-param name="param.target" select="//company"/>                       
                <xsl:with-param name="param.replacement" select="$realcompany"/>                   
            </xsl:call-template>
        </xsl:element>                      
    </xsl:template>
    <!--replace value in department block with realdepartment variable condition-->
    <xsl:template match="department[parent::FormDataRequest]">
        <xsl:element name="{name()}">                                    
            <xsl:call-template name="value-to-replace">                       
                <xsl:with-param name="param.str" select="."/>                       
                <xsl:with-param name="param.target" select="//company"/>                       
                <xsl:with-param name="param.replacement" select="$realdepartment"/>                   
            </xsl:call-template>
        </xsl:element>                      
    </xsl:template>
    <!--copy all nodes-->    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>    
</xsl:stylesheet>

结果将如预期:

<FormDataRequest>   
  <Name>Bob</Name>
  <sn>Ross</sn>
  <company>Co company 1</company>
  <department>Paint bucket</department>
</FormDataRequest>
另一答案

那么,你在<xsl:apply-templates select="@*|node()" />结果元素中的FormDataRequest处理现有的子节点,并且你使用身份转换来复制它们。如果您想要排除这两个元素,建议对现有代码进行一次更改,请将<xsl:apply-templates select="@*|node()" />更改为<xsl:apply-templates select="@*|node() except (company, department)" />

以上是关于Xslt根据条件规则引用另一个元素来更改元素值的主要内容,如果未能解决你的问题,请参考以下文章

如果值匹配,XSLT 会更改兄弟元素的子元素值

使用 xslt 引用具有不同命名空间的元素

基于另一个变量的 XSLT 元素选择

XSLT 2.0:根据 for-each -group 的当前索引评估和修改元素值

我的javascript代码有啥问题-根据条件(存在另一个元素)删除HTML元素-初学者

如何获取具有相同名称的元素并根据 XSLT 中的子节点值对它们进行排序