4

我需要转换 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>
4

5 回答 5

5

由于您使用的是 XSLT 2.0,因此您可以separatorxsl: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>

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

于 2012-10-24T15:06:07.190 回答
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>
于 2012-10-24T13:37:31.813 回答
2

你很亲密。在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 具有属性,那么您的身份模板版本将放下它们。

于 2012-10-24T13:39:23.643 回答
2

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

<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>
于 2012-10-24T14:27:00.620 回答
1

所有的反应似乎都不错,但我认为这种方法更干净(只需用这个替换你的 ManagerFirstName 模板):

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

更新:

如果您想让逗号仅在两个节点都存在且不为空时出现,您可以使用带有字符串长度的 if :

<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>
于 2012-10-24T15:39:52.907 回答