我有一个数据库字段,我正在拉出xml。此字段包含来自多个XML Feed的内容,我需要两个。我在页面上显示XML并使用XSLT对其进行格式化。
我的问题是,每个消息中最多可以有40个元素,我正在寻找大约30个。然而,并非所有消息都将包含所有30个。我需要帮助找出如何删除列没有可显示的数据。
如果我可以使用XSLT那么好,如果它是JavaScript(Jquery)那么那也没关系。一次永远不会有多行和一个标题。
以下是XML
的示例<MessageToUser>
<Name>Bob</Name>
<MessageType>Text Message</MessageType>
<MessageID>121223</MessageID>
<ResponseTo />
<Message>Call Me Please </Message>
<OfficePhone>555-555-1212</OfficePhone>
<CellPhone>555-555-5555</CellPhone>
</MessageToUser>
这是我正在使用的XSL
<xsl:template match="/">
<html>
<head>
<style type="text/css">
.Header{min-width: 100px;background-color:#9acddd;}
</style>
</head>
<body>
<table border="1">
<tr>
<th class="Header">Name</th>
<th class="Header">Message</th>
<th class="Header">Cell Phone</th>
<th class="Header">Office Phone</th>
<th class="Header">Message Type</th>
<th class="Header">Message Time</th>
<th class="Header">Message ID</th>
</tr>
<xsl:for-each select="MessageFromUser">
<tr>
<td><xsl:value-of select="Name" /></td>
<td><xsl:value-of select="Message" /></td>
<td><xsl:value-of select="CellPhone" /></td>
<td><xsl:value-of select="OfficePhone" /></td>
<td><xsl:value-of select="MessageType" /></td>
<td><xsl:value-of select="MessageTime" /></td>
<td><xsl:value-of select="MessageID" /></td>
</tr>
</xsl:for-each>
<xsl:for-each select="MessageToUser">
<tr>
<td><xsl:value-of select="Name" /></td>
<td><xsl:value-of select="Message" /></td>
<td><xsl:value-of select="CellPhone" /></td>
<td><xsl:value-of select="OfficePhone" /></td>
<td><xsl:value-of select="MessageType" /></td>
<td><xsl:value-of select="MessageTime" /></td>
<td><xsl:value-of select="MessageID" /></td>
</tr>
</xsl:for-each>
</table>
</body>
使用此XML MessageTime为空,应删除该列。
提前感谢您的帮助。
答案 0 :(得分:3)
这种转变:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" exclude-result-prefixes="my" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:Layout>
<html>
<head>
<style type="text/css">
.Header{min-width: 100px;background-color:#9acddd;}
</style>
</head>
<body>
<table border="1">
<tr>
<header name="Name">Name</header>
<header name="Message">Message</header>
<header name="CellPhone">Cell Phone</header>
<header name="OfficePhone">Office Phone</header>
<header name="MessageType">Message Type</header>
<header name="MessageTime">Message Time</header>
<header name="MessageID">Message ID</header>
</tr>
<every select="MessageFromUser">
<tr>
<Name/>
<Message/>
<CellPhone/>
<OfficePhone/>
<MessageType/>
<MessageTime/>
<MessageID/>
</tr>
</every>
<every select="MessageToUser">
<tr>
<Name/>
<Message/>
<CellPhone/>
<OfficePhone/>
<MessageType/>
<MessageTime/>
<MessageID/>
</tr>
</every>
</table>
</body>
</html>
</my:Layout>
<xsl:variable name="vLayout" select="document('')/*/my:Layout/*"/>
<xsl:variable name="vDoc" select="/"/>
<xsl:template match="node()|@*">
<xsl:param name="pContextNode"/>
<xsl:copy>
<xsl:apply-templates select="node()|@*">
<xsl:with-param name="pContextNode" select="$pContextNode"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match=
"Name|Message|CellPhone|OfficePhone|MessageType|MessageTime|MessageID">
<xsl:param name="pContextNode"/>
<xsl:if test="not($vDoc/*/*[not(*[name()=name(current())])])">
<td><xsl:value-of select="$pContextNode/*[name()=name(current())]"/></td>
</xsl:if>
</xsl:template>
<xsl:template match="/*">
<xsl:apply-templates select="$vLayout"/>
</xsl:template>
<xsl:template match="header">
<xsl:if test="not($vDoc/*/*[not(*[name()=current()/@name])])">
<th class="Header"><xsl:value-of select="."/></th>
</xsl:if>
</xsl:template>
<xsl:template match="every">
<xsl:variable name="vLayoutTop" select="."/>
<xsl:for-each select="$vDoc/*/*[name()=current()/@select]">
<xsl:apply-templates select="$vLayoutTop/*">
<xsl:with-param name="pContextNode" select="."/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
应用于此XML文档(提供的文档并添加了MessageFromUser
):
<Messages>
<MessageFromUser>
<Name>Bob</Name>
<MessageType>Text Message</MessageType>
<MessageID>121223</MessageID>
<ResponseTo />
<Message>Call Me Please </Message>
<OfficePhone>555-555-1212</OfficePhone>
<CellPhone>555-555-5555</CellPhone>
</MessageFromUser>
<MessageToUser>
<Name>Bob</Name>
<MessageType>Text Message</MessageType>
<MessageID>121223</MessageID>
<ResponseTo />
<Message>Call Me Please </Message>
<OfficePhone>555-555-1212</OfficePhone>
<CellPhone>555-555-5555</CellPhone>
</MessageToUser>
</Messages>
生成所需的输出,其中不显示空列1MessageTime`:
<html xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my:my">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
.Header{min-width: 100px;background-color:#9acddd;}
</style></head>
<body>
<table border="1">
<tr>
<th class="Header">Name</th>
<th class="Header">Message</th>
<th class="Header">Cell Phone</th>
<th class="Header">Office Phone</th>
<th class="Header">Message Type</th>
<th class="Header">Message ID</th>
</tr>
<tr>
<td>Bob</td>
<td>Call Me Please </td>
<td>555-555-5555</td>
<td>555-555-1212</td>
<td>Text Message</td>
<td>121223</td>
</tr>
<tr>
<td>Bob</td>
<td>Call Me Please </td>
<td>555-555-5555</td>
<td>555-555-1212</td>
<td>Text Message</td>
<td>121223</td>
</tr>
</table>
</body>
</html>
请注意:
更好的设计(填空)用于,用于分隔代码和演示文稿。 这是最基本和最强大的XSLT设计(填空)模式之一。
此设计允许相同的代码用于不同的布局(作为参数传递)以产生完全不同的结果。
标识规则“按原样”复制布局的所有非变量节点。
我们仅覆盖布局的“变量”部分的身份规则。
辅助元素every
指定应执行迭代处理。
在实际应用中,<my:Layout>
元素将作为单独的XML文档驻留在单独的文件中,在这种情况下,必须将document('')/*
替换为{{ 1}}。当此文件URI作为参数传递给XSLT转换时,可以实现最大的通用性。
为了处理至少在一个记录中至少出现一次的字段/列而测试的条件是(对于标题):
document('theFileURI')
细胞的类似条件是:
not($vDoc/*/*[not(*[name()=current()/@name])])
答案 1 :(得分:0)
你能这样做吗?
<xsl:if test="MessageTime">
<td><xsl:value-of select="MessageTime" /></td>
</xsl:if>
答案 2 :(得分:0)
这个XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:key name="notEmptyAll" match="/root/MessageToUser/*" use="local-name()"/>
<xsl:template match="root">
<html>
<head>
<style type="text/css">
th {min-width: 100px;background-color:#9acddd;}
</style>
</head>
<body>
<table border="1">
<tr>
<xsl:apply-templates select="MessageToUser[1]/*" mode="header"/>
</tr>
<xsl:apply-templates select="MessageToUser"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="*" mode="header">
<xsl:if test="count( key('notEmptyAll', local-name())[text()] ) != 0">
<th>
<xsl:value-of select="local-name()"/>
</th>
</xsl:if>
</xsl:template>
<xsl:template match="MessageToUser">
<tr>
<xsl:apply-templates select="*" mode="tbody"/>
</tr>
</xsl:template>
<xsl:template match="*" mode="tbody">
<xsl:if test="count( key('notEmptyAll', local-name())[text()] ) != 0">
<td>
<xsl:value-of select="."/>
</td>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
使用此XML输入:
<root>
<MessageToUser>
<Name>Bob</Name>
<MessageType>Text Message</MessageType>
<MessageID>121223</MessageID>
<ResponseTo> </ResponseTo>
<Message>Call Me Please </Message>
<OfficePhone></OfficePhone>
<CellPhone>555-555-5555</CellPhone>
</MessageToUser>
<MessageToUser>
<Name></Name>
<MessageType>Text Message</MessageType>
<MessageID>121223</MessageID>
<ResponseTo> </ResponseTo>
<Message>Call Me Please </Message>
<OfficePhone>555-555-1212</OfficePhone>
<CellPhone>555-555-5555</CellPhone>
</MessageToUser>
</root>
将提供此结果(摘录):
<table border="1">
<tr>
<th>Name</th>
<th>MessageType</th>
<th>MessageID</th>
<th>Message</th>
<th>OfficePhone</th>
<th>CellPhone</th>
</tr>
<tr>
<td>Bob</td>
<td>Text Message</td>
<td>121223</td>
<td>Call Me Please </td>
<td></td>
<td>555-555-5555</td>
</tr>
<tr>
<td></td>
<td>Text Message</td>
<td>121223</td>
<td>Call Me Please </td>
<td>555-555-1212</td>
<td>555-555-5555</td>
</tr>
</table>
因此,显示所有至少有一个非空值的元素。
local-name
对您来说效率不高,因为标题会像OfficePhone
一样。这可以通过子串或“词汇”来解决。请自由评论什么更适合,因为从你的XML摘录中看不出来。
我没有使用MessageFromUser
,因为你没有提供XML样本。