使用逗号连接两个节点值

时间:2012-10-24 13:30:20

标签: xml xslt

我需要转换XML并遇到一些问题......

当前XML:

<?xml version="1.0" encoding="utf-8"?>
 <Employees>
  <Employee>
   <ManagerFirstName>Joe</ManagerFirstName>
   <ManagerLastName>Schmoe</ManagerLastName>
  </Employee>
 </Employees>

期望输出:

<?xml version="1.0" encoding="utf-8"?>
 <Employees>
  <Employee>
   <supervisorName>Schmoe, Joe</supervisorName>
  </Employee>
 </Employees>

当前XSL:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
  <xsl:template match="/">
    <xsl:apply-templates select="*"/>
  </xsl:template>
  <xsl:template match="node()">
    <xsl:copy><xsl:apply-templates select="node()"/></xsl:copy>
  </xsl:template>
  <xsl:template match="ManagerFirstName">
        <supervisorName>
        <xsl:apply-templates select="node()"/>
        <xsl:value-of  select="/ManagerLastName"/>
        <xsl:text>, </xsl:text>
        <xsl:value-of select="/ManagerFirstName"/>
        </supervisorName>
  </xsl:template>
</xsl:stylesheet>

这不起作用,我无法弄清楚。它目前输出的XML如下所示:

<?xml version="1.0" encoding="utf-8"?>
 <Employees>
  <Employee>
   <supervisorName>Joe, </supervisorName>
   <ManagerLastName>Schmoe/ManagerLastName>
  </Employee>
 </Employees>

我觉得我太近了......

更新 我如何确保如果ManagerFirstName和ManagerLastName为空,那supervisorName中没有逗号?

更新2

<?xml version="1.0" encoding="UTF-8" ?>
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/> <xsl:strip-space elements="*"/>
 <xsl:template match="/">
   <xsl:apply-templates select="*"/>
 </xsl:template>
 <xsl:template match="@*|node()">
   <xsl:copy>
     <xsl:apply-templates select="@*|node()"/>
   </xsl:copy>
 </xsl:template>
 <xsl:template match="Employee">
   <tbl_EmployeeList><xsl:apply-templates select="@*|node()"/></tbl_EmployeeList>
 </xsl:template>
 <xsl:template match="tbl_EmployeeList">
   <xsl:copy>
     <xsl:apply-templates select="@*|node()"/>
       <supervisorName>
         <xsl:value-of select="(ManagerLastName,ManagerFirstName)" separator=", "/>
       </supervisorName>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

5 个答案:

答案 0 :(得分:4)

由于您使用的是XSLT 2.0,因此可以使用separator中的xsl:value-of属性...

XML输入

<Employees>
    <Employee>
        <ManagerFirstName>Joe</ManagerFirstName>
        <ManagerLastName>Schmoe</ManagerLastName>
    </Employee>
</Employees>

XSLT 2.0

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

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

    <xsl:template match="Employee">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <supervisorName>
                <xsl:value-of select="(ManagerLastName,ManagerFirstName)" separator=", "/>
            </supervisorName>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XML输出

<Employees>
   <Employee>
      <supervisorName>Schmoe, Joe</supervisorName>
   </Employee>
</Employees>

注意:如果没有ManagerLastNameManagerFirstName,则不会输出分隔符。

答案 1 :(得分:3)

您可以通过以下方式执行此操作:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Employee">
        <Employee>
            <supervisorName><xsl:value-of select="concat(ManagerLastName, ', ', ManagerFirstName)"/></supervisorName>
        </Employee>
    </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:1)

你很亲密。在ManagerFirstName模板中,您需要稍微不同的XPath来提取姓氏:

<xsl:template match="ManagerFirstName">
    <supervisorName>
        <xsl:value-of select="../ManagerLastName"/>
        <xsl:text>, </xsl:text>
        <xsl:apply-templates select="node()"/>
    </supervisorName>
</xsl:template>

apply-templates足以为您提供ManagerFirstName的值,您不需要特定的value-of。然后,您需要一个无操作模板来阻止它独立复制姓氏

<xsl:template match="ManagerLastName" />

另请注意,通常的身份模板会匹配并将应用模板与@*|node()匹配,而不仅仅是node() - 它在您的示例文档中没有任何区别,因为您没有使用任何属性,但是您的原始XML具有属性,那么您的身份模板版本将丢弃它们。

答案 3 :(得分:1)

这是一个完全“推送式”解决方案

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

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

 <xsl:template match="Employee">
  <supervisorName><xsl:apply-templates/></supervisorName>
 </xsl:template>

 <xsl:template match="Employee/*">
  <xsl:value-of select="concat(', ', .)"/>
 </xsl:template>
 <xsl:template match="Employee/*[1]"><xsl:apply-templates/></xsl:template>
</xsl:stylesheet>

答案 4 :(得分:1)

所有回复似乎都很好,但我认为这种方法更简洁(只需用此替换您的ManagerFirstName模板):

<xsl:template match="Employee">
    <supervisorName>
        <xsl:value-of select="concat(ManagerLastName,', ',ManagerFirstName)"/>
    </supervisorName>
</xsl:template>

<强>更新

如果你想只在两个节点都存在且不为空时才显示逗号,你可以使用if with string-length:

<xsl:template match="Employee">
    <supervisorName>
        <xsl:value-of select="ManagerLastName"/>
        <xsl:if test="string-length(ManagerLastName) and string-length(ManagerFirstName)">
            <xsl:text> ,</xsl:text>
        </xsl:if>
        <xsl:value-of select="ManagerFirstName"/>
    </supervisorName>
</xsl:template>

更新2: 然而,这是一个更简洁的解决方案,遵循xslt 2.0方法,但也涵盖了空节点的情况。

<xsl:template match="Employee">
    <supervisorName>
        <xsl:value-of select="(ManagerLastName[text()],ManagerFirstName[text()])" separator=", "/>
    </supervisorName>
</xsl:template>