更改指定路径下的属性值

时间:2016-09-12 13:02:22

标签: xml xslt-2.0

我需要xsl模板,指定'path_type'指定的'path',属性'name'值与'old_value'匹配,将'old_value'替换为'new_value'

我创建了xsl模板,正确处理了'element_type','old_value','new_value'参数。我堆放着处理'path'参数。 下面是输入xml

<?xml version="1.0" encoding="utf-8"?>
<storage name="hdd1">
    <folder name="root">
        <folder name="sub1">
            <folder name="sub1-sub">
                <file name="temp-docs"/>
                <folder name="temp-docs"/>
                <folder name="temp-pictures"/>
            </folder>
        </folder>
        <folder name="sub2">
            <folder name="temp-docs">
                <folder name="inner-temp-bar"/>
            </folder>
            <folder name="temp-pictures"/>
        </folder>
    </folder>
    <folder name="temp-docs"/>
    <folder name="temp-pictures"/>
</storage>

接下来是XSL设计:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:param name="element_type"/>
    <xsl:param name="path"/>
    <xsl:param name="old_value"/>
    <xsl:param name="new_value"/>

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

    <xsl:template match="@*">
        <xsl:choose>
            <xsl:when test="contains(., $old_value)
            and local-name() = 'name'
            and name(..) = $element_type
            and ancestor::*[2]/@name = $path">
                <xsl:attribute name="name">
                    <xsl:value-of select="substring-before(., $old_value)"/>
                    <xsl:value-of select="$new_value"/>
                    <xsl:value-of select="substring-after(., $old_value)"/>
                </xsl:attribute>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="* | @* | text()"/>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

输入参数:

'element_type' = 'folder'   
'old_value' = 'temp-'  
'new_value' = ''  
'path'= 'sub2'  

上面的XML结果的上述XSL应用程序是(重命名所有&#39;文件夹&#39;元素,但不是&#39;文件夹&#39;元素,名称=&#34; inner-temp-bar):

<?xml version="1.0" encoding="UTF-8"?>
<storage name="hdd1">
    <folder name="root">
        <folder name="sub1">
            <folder name="sub1-sub">
                <file name="temp-docs"/>
                <folder name="temp-docs"/>
                <folder name="temp-pictures"/>
            </folder>
        </folder>
        <folder name="sub2">
            <folder name="docs">
                <folder name="inner-temp-docs"/>
            </folder>
            <folder name="pictures"/>
        </folder>
    </folder>
    <folder name="temp-docs"/>
    <folder name="temp-pictures"/>
</storage>

目标是重命名指定路径下的所有文件夹和子文件夹,例如:
- &#39;路径&#39; =&#39; root / sub2&#39;将重命名所有&#39;文件夹&#39;里面的元素&sub;&#39; sub2&#39;元件;
- &#39;路径&#39; =&#39; root&#39;将重命名所有&#39;文件夹&#39;里面的元素&#39; sub1&#39;和&#39; sub2&#39;元素。
我如何处理&#39;路径&#39;参数达到上述目标?

1 个答案:

答案 0 :(得分:1)

这是一个XSLT 2.0样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:param name="element_type" select="'folder'"/>
    <xsl:param name="path" select="'root/sub2'"/>
    <xsl:param name="old_value" select="'temp-'"/>
    <xsl:param name="new_value" select="''"/>

    <xsl:param name="path-tokens" as="xs:string*" select="tokenize($path, '/')"/>

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

    <xsl:template match="*[string-join(ancestor-or-self::*[position() le count($path-tokens)]/@name, '/') eq $path]//*[local-name() eq $element_type]/@name[contains(., $old_value)]">
        <xsl:attribute name="{name()}" select="replace(., $old_value, $new_value)"/>
    </xsl:template>

</xsl:stylesheet>