我需要转换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>
答案 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>
注意:如果没有ManagerLastName
或ManagerFirstName
,则不会输出分隔符。
答案 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>