用于合并2个节点的XSL/XSLT/XPath

用于合并2个节点的XSL/XSLT/XPath,xslt,xpath,Xslt,Xpath,我有一些包含记录文件路径和文件名的节点的XML。我需要一个XSLT将它们转换为FilePathAndName的单个节点。文件路径值可能以“\”结尾,也可能不以“\”结尾。任何值都可以为空。FilePathAndName值必须以'\'结尾,如果它只是一个文件夹名 转换将从C#应用程序调用,因此我想我可能可以使用任何版本的XSLT 我已经做了一部分,但正在努力完成完整的解决方案,包括在输入中考虑可选的'\'值 以下是一些示例输入XML: <Task> <Action Act

我有一些包含记录
文件路径
文件名
的节点的XML。我需要一个
XSLT
将它们转换为
FilePathAndName
的单个节点。
文件路径
值可能以“\”结尾,也可能不以“\”结尾。任何值都可以为空。
FilePathAndName
值必须以'\'结尾,如果它只是一个文件夹名

转换将从C#应用程序调用,因此我想我可能可以使用任何版本的XSLT

我已经做了一部分,但正在努力完成完整的解决方案,包括在输入中考虑可选的'\'

以下是一些示例输入XML:

<Task>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePath" ParameterValue="folder1\sub-folder1" />   <!-- FilePath doesn't end in '\' -->
          <Parameter ParameterName="FileName" ParameterValue="file1" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePath" ParameterValue="folder2\sub-folder2\" />  <!-- FilePath ends in '\' -->
          <Parameter ParameterName="FileName" ParameterValue="file2" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePath" ParameterValue="" />  <!-- Empty FilePath -->
          <Parameter ParameterName="FileName" ParameterValue="file3" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePath" ParameterValue="folder4\sub-folder4" />   <!-- Empty FileName -->
          <Parameter ParameterName="FileName" ParameterValue="" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePath" ParameterValue="" />  <!-- Empty FilePath and FileName -->
          <Parameter ParameterName="FileName" ParameterValue="" />
    </Action>
    <Action ActionName="GetRateData">
          <!-- No FilePath Node -->
          <Parameter ParameterName="FileName" ParameterValue="file5" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePath" ParameterValue="folder6\sub-folder6" />
          <!-- No FileName Node -->
    </Action>
    <Action ActionName="GetRateData">
          <!-- No FilePath or FileName Node -->
    </Action>
</Task>

应将其转换为以下内容:

<Task>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePathAndName" ParameterValue="folder1\sub-folder1\file1" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePathAndName" ParameterValue="folder2\sub-folder2\file2" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePathAndName" ParameterValue="file3" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePathAndName" ParameterValue="folder4\sub-folder4\" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePathAndName" ParameterValue="" />
    </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePathAndName" ParameterValue="file5" />
    </Action>
   <Action ActionName="GetRateData">
      <Parameter ParameterName="FilePathAndName" ParameterValue="folder6\sub-folder6\"/>
   </Action>
    <Action ActionName="GetRateData">
          <Parameter ParameterName="FilePathAndName" ParameterValue="" />
    </Action>
</Task>

这是我尝试的解决方案:

<xsl:template match="Task">
    <Task>

      <xsl:for-each select="Action">
        <Action>
          <xsl:copy-of select="@ActionName"/>

          <xsl:for-each select="Parameter">
            <Parameter>

              <xsl:choose>

                <xsl:when test="@ParameterName = 'FilePath'">
                  <xsl:attribute name="ParameterName">
                    <xsl:text>FilePathAndName</xsl:text>
                  </xsl:attribute>
                  <xsl:attribute name="ParameterValue">
                    <xsl:value-of select="@ParameterValue" />\<xsl:value-of select="(../Parameter[@ParameterName='FileName'])[1]/@ParameterValue" /></xsl:attribute>

                    <!-- TODO: Don't include '\' if FilePath is empty. -->
                    <!-- TODO: What if FilePath is missing? -->
                </xsl:when>

                <xsl:when test="@ParameterName = 'FileName'">
                    <!-- FileName will be consumed above. -->
                </xsl:when>

                <xsl:otherwise>
                  <xsl:copy-of select="@ParameterName"/>
                  <xsl:copy-of select="@ParameterValue"/>
                </xsl:otherwise>
              </xsl:choose>
            </Parameter>
          </xsl:for-each>

        </Action>
      </xsl:for-each>

    </Task>
  </xsl:template>
</xsl:stylesheet>

文件路径和名称
\
这将产生以下结果(其余问题请参见下面的XML注释):


如果您可以使用XSLT2.0,那么您可以这样做

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

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

  <xsl:template match="Action">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <Parameter FileNameAndPath="{replace(Parameter[@ParameterName='FilePath']/@ParameterValue, '([^\\])$', '$1\\')}{Parameter[@ParameterName='FileName']/@ParameterValue}" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

请你展示一下你的半路尝试,因为你可能离解决方案不远了!另外,您能否说您是否可以使用XSLT2.0或更高版本?非常感谢。太棒了,谢谢!XSL和XPath的内容显然比我从我读过的这本小书中得到的要多。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" />

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

  <xsl:template match="Action">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <Parameter FileNameAndPath="{replace(Parameter[@ParameterName='FilePath']/@ParameterValue, '([^\\])$', '$1\\')}{Parameter[@ParameterName='FileName']/@ParameterValue}" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes" />

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

  <xsl:template match="Action">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <Parameter>
        <xsl:attribute name="FileNameAndPath">
          <xsl:variable name="FilePath" select="Parameter[@ParameterName='FilePath']/@ParameterValue" />
          <xsl:value-of select="$FilePath" />
          <xsl:if test="$FilePath != '' and substring($FilePath, string-length($FilePath)) != '\'">\</xsl:if>
          <xsl:value-of select="Parameter[@ParameterName='FileName']/@ParameterValue" />
        </xsl:attribute>
      </Parameter>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>