替换从另一个属性获取的值

时间:2019-05-16 16:02:00

标签: xml xslt xmlstarlet

我正在尝试使用 xmlstarlet 在另一个已经存在的值中重复一个值,但我没有找到一种方法。这是一个例子:

当前XML:

<MsgList>
    <Msg N="/Workflow/StateObject" I="0" T="03 May 2012 09:32:32.795000" S="Inquiry" D="Inquiry">
        <M N="eventid">999999</M>
        <M N="hist-time">19 Oct 2017 10:50:35 Etc/UTC</M>
        <M N="hist-user">System</M>
        <M N="key">1</M>
        <M N="key-so">357251</M>
        <G N="_StateObject">
            <F N="CurrentState" T="N">44</F>
            <F N="Version" T="S">16.16</F>
            <F N="Status" T="S">OK</F>
        </G>
    </Msg>
    <Msg N="/Workflow/StateObject" I="0" T="05 Feb 2013 15:26:32.971000" S="Inquiry" D="Inquiry">
        <M N="eventid">999999</M>
        <M N="hist-time">19 Oct 2017 10:50:36 Etc/UTC</M>
        <M N="hist-user">System</M>
        <M N="key">2</M>
        <M N="key-so">618751</M>
        <G N="_StateObject">
            <F N="CurrentState" T="N">44</F>
            <F N="Version" T="S">16.16</F>
            <F N="Status" T="S">OK</F>
        </G>
    </Msg>
</MsgList>

所需的XML:

<MsgList>
    <Msg N="/Workflow/StateObject" I="0" T="03 May 2012 09:32:32.795000" S="Inquiry" D="Inquiry">
        <M N="eventid">999999</M>
        <M N="hist-time">19 Oct 2017 10:50:35 Etc/UTC</M>
        <M N="hist-user">System</M>
        <M N="key">357251</M>
        <M N="key-so">357251</M>
        <G N="_StateObject">
            <F N="CurrentState" T="N">44</F>
            <F N="Version" T="S">16.16</F>
            <F N="Status" T="S">OK</F>
        </G>
    </Msg>
    <Msg N="/Workflow/StateObject" I="0" T="05 Feb 2013 15:26:32.971000" S="Inquiry" D="Inquiry">
        <M N="eventid">999999</M>
        <M N="hist-time">19 Oct 2017 10:50:36 Etc/UTC</M>
        <M N="hist-user">System</M>
        <M N="key">618751</M>
        <M N="key-so">618751</M>
        <G N="_StateObject">
            <F N="CurrentState" T="N">44</F>
            <F N="Version" T="S">16.16</F>
            <F N="Status" T="S">OK</F>
        </G>
    </Msg>
</MsgList>

“ key”必须具有与“ key-so”相同的值;我的 xslt 文件现在是这样的:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="node()|@*">
        <xsl:attribute name="xgenkey">
            <xsl:text>for pros</xsl:text>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

有可能做到吗?我如何使用此工具来做到这一点?

1 个答案:

答案 0 :(得分:2)

您的第二个模板实际上应该是M元素,其N属性为“ key”

<xsl:template match="M[@N='key']">

然后,在模板内部替换值,您可以像这样获得新值(其中..代表父节点)

<xsl:value-of select="../M[@N='key-so']" />

尝试使用此XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="M[@N='key']">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:value-of select="../M[@N='key-so']" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

实际上,您可以通过直接匹配子文本节点来稍微简化它。这也可以工作(假设M[@N='key']始终存在一个子文本节点)。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="M[@N='key']/text()">
        <xsl:value-of select="../../M[@N='key-so']" />
    </xsl:template>
</xsl:stylesheet>