尝试使用 For-Each 时,它会破坏格式编号并在 xslt 1.0 中显示 NaN
When trying to use For-Each, it breaks the format-number and displays NaN in xslt 1.0
我正在开发 XSLT 1.0 版(抱歉,我知道 2.0 版要好得多!)感谢这个出色的社区,它确实有所作为。我现在又卡住了。我正在尝试将这个原始且不太吸引人的 XML 转换为 .csv:
<transmissions>
<ES_TRANSMISSION>
<tx_txblocks>
<ES_TXBLOCK>
<txb_announcedtime>
<ESP_TIMEDURATION time="25:00:00.000" tvdayhours="25" hours="1" minutes="00" />
</txb_announcedtime>
<duration>
<ESP_TIMEDURATION duration="50:00.000" />
</duration>
<product>
<ES_PRODUCT p_product_calculatedbroadcasttitle="4" />
</product>
</ES_TXBLOCK>
</tx_txblocks>
<tx_date>
<ESP_DATE date="2019-10-12" dateindays="43383" day="12" dayname="Saturday" month="10" monthname="October" productionweeknumber="41" weekNumberYear="2019" weekdaynumber="6" weeknumber="41" year="2019" />
</tx_date>
<tx_duration>
<ESP_TIMEDURATION duration="50:00.000" hours="0" minutes="50" />
</tx_duration>
<tx_channel>
<ESP_CHANNEL name="Channel A">
<popupLookups />
</ESP_CHANNEL>
</tx_channel>
</ES_TRANSMISSION>
<ES_TRANSMISSION>
<tx_txblocks>
<ES_TXBLOCK>
<txb_announcedtime>
<ESP_TIMEDURATION time="25:50:00.000" tvdayhours="25" hours="1" minutes="50" />
</txb_announcedtime>
<duration>
<ESP_TIMEDURATION duration="45:00.000" />
</duration>
<product>
<ES_PRODUCT p_product_calculatedbroadcasttitle="5" />
</product>
</ES_TXBLOCK>
</tx_txblocks>
<tx_date>
<ESP_DATE date="2019-10-12" dateindays="43383" day="12" dayname="Saturday" month="10" monthname="October" productionweeknumber="41" weekNumberYear="2019" weekdaynumber="6" weeknumber="41" year="2019" />
</tx_date>
<tx_duration>
<ESP_TIMEDURATION duration="45:00.000" hours="0" minutes="45" />
</tx_duration>
<tx_channel>
<ESP_CHANNEL name="Channel A">
<popupLookups />
</ESP_CHANNEL>
</tx_channel>
</ES_TRANSMISSION>
</transmissions>
第三方对 .csv 有一些要求,例如总是需要两个数字(排序)和大量逗号,因为......为什么不呢!
但是每次我尝试 for-each 让它报告列表中第一项以上的项目时,它都会返回 NaN。下面是我构建的 XSLT(很抱歉它太基础了)可以工作,但只考虑了第一项。我为它尝试了各种<xsl:for-each>
,但每次它都会破坏它。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output encoding="utf-8" method="text" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@day, '00')"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@month, '00')"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@year"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_txblocks/ES_TXBLOCK/txb_announcedtime/ESP_TIMEDURATION/@hours, '00')"/>
<xsl:text>:</xsl:text><xsl:value-of select="transmissions/ES_TRANSMISSION/tx_txblocks/ES_TXBLOCK/txb_announcedtime/ESP_TIMEDURATION/@minutes"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_duration/ESP_TIMEDURATION/@hours, '00')"/><xsl:text>:</xsl:text>
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_duration/ESP_TIMEDURATION/@minutes, '00')"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="translate(transmissions/ES_TRANSMISSION/tx_txblocks/ES_TXBLOCK/product/ES_PRODUCT/@p_product_calculatedbroadcasttitle, '.,', '')"/>
<xsl:text>,,,,,,,,,,,,,,,</xsl:text>
<xsl:text>TEST</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="ESP_DATE" mode="full">
<xsl:value-of select="@day"/>
<xsl:text>00</xsl:text>
</xsl:template>
<xsl:template match="ESP_DATE" mode="full">
<xsl:text>00</xsl:text>
<xsl:value-of select="@month"/>
</xsl:template>
<xsl:template match="ESP_TIMEDURATION" mode="full">
<xsl:text>00</xsl:text>
<xsl:value-of select="@hour"/>
</xsl:template>
<xsl:template match ="ES_TRANSMISSION"/>
<xsl:template match="ES_PRODUCT" mode="full"/>
</xsl:stylesheet>
任何提示或指导将不胜感激。然后我会让你们单独呆一会儿,我会尝试与我一起工作的人讨论使用 2.0,因为我有这本庞大的参考书,我知道它会非常方便!
您正在寻找这样的东西:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8" />
<xsl:template match="/">
<xsl:apply-templates select="transmissions/ES_TRANSMISSION" />
</xsl:template>
<xsl:template match="ES_TRANSMISSION">
<xsl:apply-templates select="tx_date/ESP_DATE" mode="csv" />
<xsl:text>,</xsl:text>
<xsl:apply-templates select="tx_txblocks/ES_TXBLOCK/txb_announcedtime/ESP_TIMEDURATION" mode="csv" />
<xsl:text>,</xsl:text>
<xsl:apply-templates select="tx_duration/ESP_TIMEDURATION" mode="csv" />
<xsl:text>,</xsl:text>
<xsl:value-of select="translate(tx_txblocks/ES_TXBLOCK/product/ES_PRODUCT/@p_product_calculatedbroadcasttitle, '.,', '')"/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="ESP_DATE" mode="csv">
<xsl:value-of select="format-number(@day, '00')"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="format-number(@month, '00')"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="@year"/>
</xsl:template>
<xsl:template match="ESP_TIMEDURATION" mode="csv">
<xsl:choose>
<xsl:when test="@tvdayhours">
<xsl:value-of select="format-number(@tvdayhours, '00')" />
</xsl:when>
<xsl:otherwise>00</xsl:otherwise>
</xsl:choose>
<xsl:text>:</xsl:text>
<xsl:value-of select="format-number(@hours, '00')" />
<xsl:text>:</xsl:text>
<xsl:value-of select="format-number(@minutes, '00')"/>
</xsl:template>
</xsl:stylesheet>
从您的示例数据中输出此 CSV:
12/10/2019,25:01:00,00:00:50,4
12/10/2019,25:01:50,00:00:45,5
请注意,它以 <xsl:apply-templates>
开头(参见 how <xsl:apply-templates>
works),然后 re-uses 两次 ESP_TIMEDURATION
模板以输出相同格式的两个持续时间值.
请注意,我一直在使用 <xsl:apply-templates>
,我只能建议养成这个习惯。
您可以在 /
模板中添加带有 header 行的 <xsl:text>...</xsl:text>
。
您的尝试失败,因为它不包含任何迭代:
<xsl:template match="/">
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@day, '00')"/>
<!-- ... --->
</xsl:template>
/
模板在输入 XML. 的根处恰好匹配一次
<xsl:value-of select="..." />
输出 表达式的 值。
- XPath
transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@day
从所有传输中选择 所有 匹配 @day
属性。
format-number(...)
只能格式化 一个 项,但在这种情况下它会得到多个。它采用这些项目中的第一项并对其进行格式化。
- 该模板中的所有其他输出都会发生这种情况。
/
模板在仅有效处理第一次传输的数据后结束。
使用单独的模板和 <xsl:apply-templates>
解决了这种情况(加上所有 XPath 变得更短)。
为了创建 .csv,您需要一个模板,该模板将为 XSLT 中表示记录的每个元素生成一行(我假设它在您的示例中为 ES_TRANSMISSION
)。
此模板可以是独立的 xsl:template
指令(如 Tomalak 给出的答案所示),也可以包含在 xsl:for each
指令中。
every time I try a for-each to get it to report on more than the first item on the list it comes back with NaN.
要记住的重要一点是,xsl:template
和 xsl:for each
都为其中包含的指令和表达式建立了上下文。
指令如:
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@day, '00')"/>
在以下上下文中起作用:
<xsl:template match="/">
必须改为:
<xsl:value-of select="format-number(tx_date/ESP_DATE/@day, '00')"/>
为了在以下上下文中工作:
<xsl:for-each select="transmissions/ES_TRANSMISSION">
我正在开发 XSLT 1.0 版(抱歉,我知道 2.0 版要好得多!)感谢这个出色的社区,它确实有所作为。我现在又卡住了。我正在尝试将这个原始且不太吸引人的 XML 转换为 .csv:
<transmissions>
<ES_TRANSMISSION>
<tx_txblocks>
<ES_TXBLOCK>
<txb_announcedtime>
<ESP_TIMEDURATION time="25:00:00.000" tvdayhours="25" hours="1" minutes="00" />
</txb_announcedtime>
<duration>
<ESP_TIMEDURATION duration="50:00.000" />
</duration>
<product>
<ES_PRODUCT p_product_calculatedbroadcasttitle="4" />
</product>
</ES_TXBLOCK>
</tx_txblocks>
<tx_date>
<ESP_DATE date="2019-10-12" dateindays="43383" day="12" dayname="Saturday" month="10" monthname="October" productionweeknumber="41" weekNumberYear="2019" weekdaynumber="6" weeknumber="41" year="2019" />
</tx_date>
<tx_duration>
<ESP_TIMEDURATION duration="50:00.000" hours="0" minutes="50" />
</tx_duration>
<tx_channel>
<ESP_CHANNEL name="Channel A">
<popupLookups />
</ESP_CHANNEL>
</tx_channel>
</ES_TRANSMISSION>
<ES_TRANSMISSION>
<tx_txblocks>
<ES_TXBLOCK>
<txb_announcedtime>
<ESP_TIMEDURATION time="25:50:00.000" tvdayhours="25" hours="1" minutes="50" />
</txb_announcedtime>
<duration>
<ESP_TIMEDURATION duration="45:00.000" />
</duration>
<product>
<ES_PRODUCT p_product_calculatedbroadcasttitle="5" />
</product>
</ES_TXBLOCK>
</tx_txblocks>
<tx_date>
<ESP_DATE date="2019-10-12" dateindays="43383" day="12" dayname="Saturday" month="10" monthname="October" productionweeknumber="41" weekNumberYear="2019" weekdaynumber="6" weeknumber="41" year="2019" />
</tx_date>
<tx_duration>
<ESP_TIMEDURATION duration="45:00.000" hours="0" minutes="45" />
</tx_duration>
<tx_channel>
<ESP_CHANNEL name="Channel A">
<popupLookups />
</ESP_CHANNEL>
</tx_channel>
</ES_TRANSMISSION>
</transmissions>
第三方对 .csv 有一些要求,例如总是需要两个数字(排序)和大量逗号,因为......为什么不呢!
但是每次我尝试 for-each 让它报告列表中第一项以上的项目时,它都会返回 NaN。下面是我构建的 XSLT(很抱歉它太基础了)可以工作,但只考虑了第一项。我为它尝试了各种<xsl:for-each>
,但每次它都会破坏它。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output encoding="utf-8" method="text" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@day, '00')"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@month, '00')"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@year"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_txblocks/ES_TXBLOCK/txb_announcedtime/ESP_TIMEDURATION/@hours, '00')"/>
<xsl:text>:</xsl:text><xsl:value-of select="transmissions/ES_TRANSMISSION/tx_txblocks/ES_TXBLOCK/txb_announcedtime/ESP_TIMEDURATION/@minutes"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_duration/ESP_TIMEDURATION/@hours, '00')"/><xsl:text>:</xsl:text>
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_duration/ESP_TIMEDURATION/@minutes, '00')"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="translate(transmissions/ES_TRANSMISSION/tx_txblocks/ES_TXBLOCK/product/ES_PRODUCT/@p_product_calculatedbroadcasttitle, '.,', '')"/>
<xsl:text>,,,,,,,,,,,,,,,</xsl:text>
<xsl:text>TEST</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="ESP_DATE" mode="full">
<xsl:value-of select="@day"/>
<xsl:text>00</xsl:text>
</xsl:template>
<xsl:template match="ESP_DATE" mode="full">
<xsl:text>00</xsl:text>
<xsl:value-of select="@month"/>
</xsl:template>
<xsl:template match="ESP_TIMEDURATION" mode="full">
<xsl:text>00</xsl:text>
<xsl:value-of select="@hour"/>
</xsl:template>
<xsl:template match ="ES_TRANSMISSION"/>
<xsl:template match="ES_PRODUCT" mode="full"/>
</xsl:stylesheet>
任何提示或指导将不胜感激。然后我会让你们单独呆一会儿,我会尝试与我一起工作的人讨论使用 2.0,因为我有这本庞大的参考书,我知道它会非常方便!
您正在寻找这样的东西:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8" />
<xsl:template match="/">
<xsl:apply-templates select="transmissions/ES_TRANSMISSION" />
</xsl:template>
<xsl:template match="ES_TRANSMISSION">
<xsl:apply-templates select="tx_date/ESP_DATE" mode="csv" />
<xsl:text>,</xsl:text>
<xsl:apply-templates select="tx_txblocks/ES_TXBLOCK/txb_announcedtime/ESP_TIMEDURATION" mode="csv" />
<xsl:text>,</xsl:text>
<xsl:apply-templates select="tx_duration/ESP_TIMEDURATION" mode="csv" />
<xsl:text>,</xsl:text>
<xsl:value-of select="translate(tx_txblocks/ES_TXBLOCK/product/ES_PRODUCT/@p_product_calculatedbroadcasttitle, '.,', '')"/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="ESP_DATE" mode="csv">
<xsl:value-of select="format-number(@day, '00')"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="format-number(@month, '00')"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="@year"/>
</xsl:template>
<xsl:template match="ESP_TIMEDURATION" mode="csv">
<xsl:choose>
<xsl:when test="@tvdayhours">
<xsl:value-of select="format-number(@tvdayhours, '00')" />
</xsl:when>
<xsl:otherwise>00</xsl:otherwise>
</xsl:choose>
<xsl:text>:</xsl:text>
<xsl:value-of select="format-number(@hours, '00')" />
<xsl:text>:</xsl:text>
<xsl:value-of select="format-number(@minutes, '00')"/>
</xsl:template>
</xsl:stylesheet>
从您的示例数据中输出此 CSV:
12/10/2019,25:01:00,00:00:50,4 12/10/2019,25:01:50,00:00:45,5
请注意,它以 <xsl:apply-templates>
开头(参见 how <xsl:apply-templates>
works),然后 re-uses 两次 ESP_TIMEDURATION
模板以输出相同格式的两个持续时间值.
请注意,我一直在使用 <xsl:apply-templates>
,我只能建议养成这个习惯。
您可以在 /
模板中添加带有 header 行的 <xsl:text>...</xsl:text>
。
您的尝试失败,因为它不包含任何迭代:
<xsl:template match="/">
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@day, '00')"/>
<!-- ... --->
</xsl:template>
/
模板在输入 XML. 的根处恰好匹配一次
<xsl:value-of select="..." />
输出 表达式的 值。- XPath
transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@day
从所有传输中选择 所有 匹配@day
属性。 format-number(...)
只能格式化 一个 项,但在这种情况下它会得到多个。它采用这些项目中的第一项并对其进行格式化。- 该模板中的所有其他输出都会发生这种情况。
/
模板在仅有效处理第一次传输的数据后结束。
使用单独的模板和 <xsl:apply-templates>
解决了这种情况(加上所有 XPath 变得更短)。
为了创建 .csv,您需要一个模板,该模板将为 XSLT 中表示记录的每个元素生成一行(我假设它在您的示例中为 ES_TRANSMISSION
)。
此模板可以是独立的 xsl:template
指令(如 Tomalak 给出的答案所示),也可以包含在 xsl:for each
指令中。
every time I try a for-each to get it to report on more than the first item on the list it comes back with NaN.
要记住的重要一点是,xsl:template
和 xsl:for each
都为其中包含的指令和表达式建立了上下文。
指令如:
<xsl:value-of select="format-number(transmissions/ES_TRANSMISSION/tx_date/ESP_DATE/@day, '00')"/>
在以下上下文中起作用:
<xsl:template match="/">
必须改为:
<xsl:value-of select="format-number(tx_date/ESP_DATE/@day, '00')"/>
为了在以下上下文中工作:
<xsl:for-each select="transmissions/ES_TRANSMISSION">