【问题标题】:Need help - ADD/Replace/Remove nodes in XML based on conditions using XSLT需要帮助 - 根据使用 XSLT 的条件在 XML 中添加/替换/删除节点
【发布时间】:2017-10-26 18:07:18
【问题描述】:

我必须使用 XSLT 转换以下两个 XML(输入 XML #1 和输入 XML #2)。我需要您的帮助来使用 XSLT 转换它们,因为我正在努力寻找解决方案。

提前感谢您的帮助。

输入 XML #1

<Employee>
<Summary>
    <Employee_ID>12345</Employee_ID>
    <Name>Mel Gibson</Name>
</Summary>
<Personal>
    <First_Name>Mel</First_Name>
    <Last_Name>Gibson</Last_Name>
</Personal>
<Status>
    <Active>Yes</Active>
    <Base_Location>Boston</Base_Location>
</Status>
<Summary_Information>
    <Location>California</Location>
    <Last_Formatted_Name>Samuel Gibson</Last_Formatted_Name>
</Summary_Information>
</Employee>

以上XML转换的条件是

如果 XML#1 中存在 Last_Name 节点,则该节点应在转换后保存 Last_Formatted_Name 的值并删除 来自 XML#1 的 Last_Formatted_Name 节点。

输出应如下所示。请注意 Last_Name 持有 Last_Formatted_Name 的值,并且 Last_Formatted_Name 已被删除。

<Employee>
<Summary>
    <Employee_ID>12345</Employee_ID>
    <Name>Mel Gibson</Name>
</Summary>
<Personal>
    <First_Name>Mel</First_Name>
    <Last_Name>Samuel Gibson</Last_Name>
</Personal>
<Status>
    <Active>Yes</Active>
    <Base_Location>Boston</Base_Location>
</Status>
<Summary_Information>
    <Location>California</Location>
</Summary_Information>
</Employee>

输入 XML #2

<Employee>
<Summary>
    <Employee_ID>12345</Employee_ID>
    <Name>Mel Gibson</Name>
</Summary>
<Personal>
    <First_Name>Mel</First_Name>
</Personal>
<Status>
    <Active>Yes</Active>
    <Base_Location>Boston</Base_Location>
</Status>
<Summary_Information>
    <Location>California</Location>
    <Last_Formatted_Name>Samuel Gibson</Last_Formatted_Name>
</Summary_Information>
</Employee>

转换 XML# 2 的条件是:如果输入 XML 中不存在 Last_Name,则应在 First_Name 节点之后立即创建节点 Last_Name,并应保存 Last_Formatted_Name 的值

输出应如下所示。请注意 Last_Name 节点是在 First_Name 和 Last_Formatted_Name 节点被删除之后创建的。

<Employee>
<Summary>
    <Employee_ID>12345</Employee_ID>
    <Name>Mel Gibson</Name>
</Summary>
<Personal>
    <First_Name>Mel</First_Name>
    <Last_Name>Samuel Gibson</Last_Name>
</Personal>
<Status>
    <Active>Yes</Active>
    <Base_Location>Boston</Base_Location>
</Status>
<Summary_Information>
    <Location>California</Location>
</Summary_Information>
</Employee>

遵循 XSLT 是我为实现此目的而编写的,但不会产生我想要的输出。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()" mode="#default">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Personal">

    <xsl:if test="exists(Last_Name)">
    <xsl:copy>
            <xsl:apply-templates/>
        <Last_Name>
            <xsl:value-of select="//Last_Formatted_Name"/>
        </Last_Name>
        </xsl:copy>
    </xsl:if>
</xsl:template>

<xsl:template match="Personal">
<xsl:if test="not(Last_Name)">
    <xsl:copy>
            <xsl:apply-templates/>
        <Last_Name>
            <xsl:value-of select="//Last_Formatted_Name"/>
        </Last_Name>
        </xsl:copy>
    </xsl:if>
</xsl:template>

【问题讨论】:

  • 请分享您的 XSLT 代码。共享的 XML 没有 &lt;/Employee&gt; 节点,因此格式不正确。你的要求也不清楚。您想同时使用这两个 XML 作为 XSLT 的输入,还是正在寻找一个通用的 XSLT 来分别处理这两个 XML 以将输入转换为所需的输出?
  • 嗨 Aniket,感谢您对此进行调查。我写了以下
  • 嗨 Aniket,我已经用我正在尝试的 XSLT 更新了原始问题。是的,我希望我们两个 XML 同时作为 XSLT 的输入。一个 XSLT 应该同时处理这两种 XML。当我在 StackOverflow 中发布问题时,似乎 由于格式问题而丢失了

标签: xml xslt


【解决方案1】:

请尝试以下 XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />

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

    <!-- modifies the value of <Last_Name> if it exists -->
    <xsl:template match="Last_Name">
        <xsl:copy>
            <xsl:value-of select="../../Summary_Information/Last_Formatted_Name" />
        </xsl:copy>
    </xsl:template>

    <!-- if <Last_Name> does not exist, creates a last name with the appropriate value -->
    <xsl:template match="Personal[not(Last_Name)]">
        <xsl:copy>
            <xsl:apply-templates />
            <Last_Name>
                <xsl:value-of select="../Summary_Information/Last_Formatted_Name" />
            </Last_Name>
        </xsl:copy>
    </xsl:template>

    <!-- removes the node -->
    <xsl:template match="Last_Formatted_Name" />
</xsl:stylesheet>

【讨论】:

  • 谢谢 Aniket,我现在就试试这个,让你知道结果
  • 嗨 Aniket,我的 XML 和 XSLT 出现了一些问题。个人节点下的输入 XML 中可能存在更多节点。因此,对于上面的 XSLT,last_name 总是作为“个人”节点下的最后一个标记插入。取而代之的是,Last_Name 标记应插入 First_Name 标记之后。您知道如何更改我的 XSLT 以使其正常工作吗?
  • 我也发布了一个新问题。 stackoverflow.com/questions/47146870/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多