在XSLT中使用动态匹配

时间:2013-06-04 19:48:28

标签: xslt-2.0

我有一个带有多个Xpath列表的外部文档,如下所示:

<EncrypRqField>
    <EncrypFieldRqXPath01>xpath1</EncrypFieldRqXPath01>
    <EncrypFieldRqXPath02>xpath2</EncrypFieldRqXPath02>
</EncrypRqField>

我使用这个文档来获取我想要修改的节点的Xpath。

输入XML是:

<Employees>
    <Employee>
        <id>1</id>
        <firstname>xyz</firstname>
        <lastname>abc</lastname>
        <age>32</age>
        <department>xyz</department>
    </Employee>
</Employees>

我想获得这样的东西:

<Employees>
    <Employee>
        <id>XXX</id>
        <firstname>xyz</firstname>
        <lastname>abc</lastname>
        <age>XXX</age>
        <department>xyz</department>
    </Employee>
</Employees>

XXX值是数据加密的结果,我想从文档中动态获取Xpath并更改其节点的值。

感谢。

1 个答案:

答案 0 :(得分:0)

我不确定在XSL 2.0中是否可以使用这样的东西。可能在3.0中应该有一些函数evaluate()但我不知道任何细节。

但我尝试了一些解决方法,似乎功能正常。当然它并不完美,并且在这种形式中有很多限制(例如,你需要指定绝对路径,你不能使用更复杂的XPath,如//,[]等),所以考虑它只是一个想法。但它可能是一些更容易的案例。

它基于比较两个字符串而不是评估字符串作为XPath。

带有要加密的xpath的简化xml(为简单起见,我省略了数字)。

<?xml version="1.0" encoding="UTF-8"?>
<EncrypRqField>
    <EncrypFieldRqXPath>/Employees/Employee/id</EncrypFieldRqXPath>
    <EncrypFieldRqXPath>/Employees/Employee/age</EncrypFieldRqXPath>
</EncrypRqField>

我的转变                            

    <xsl:template match="element()">
        <xsl:variable name="pathToElement">
            <xsl:call-template name="getPath">
                <xsl:with-param name="element" select="." />
            </xsl:call-template>
        </xsl:variable>

        <xsl:choose>
            <xsl:when test="$xpaths/EncrypFieldRqXPath[text() = $pathToElement]">
                <!-- If exists element with exacty same value as constructed "XPath", ten "encrypt" the content of element -->
                <xsl:copy>
                    <xsl:text>XXX</xsl:text>
                </xsl:copy>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates />
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- This template will "construct" the XPath for element under investigation. -->
    <!-- There might be an easier way (e.g. some build-in function), but it is actually out of my skill. -->
    <xsl:template name="getPath">
        <xsl:param name="element" />
        <xsl:choose>
            <xsl:when test="$element/parent::node()">
                <xsl:call-template name="getPath">
                    <xsl:with-param name="element" select="$element/parent::node()" />
                </xsl:call-template>
                <xsl:text>/</xsl:text>
                <xsl:value-of select="$element/name()" />
            </xsl:when>
            <xsl:otherwise />
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>