Xml XSLT-从模板中删除空白
我正在使用XML存储一个小的联系人列表,并试图编写一个XSL模板,将其转换为CSV文件。我遇到的问题是输出中的空白 输出:Xml XSLT-从模板中删除空白,xml,xslt,Xml,Xslt,我正在使用XML存储一个小的联系人列表,并试图编写一个XSL模板,将其转换为CSV文件。我遇到的问题是输出中的空白 输出: Friend, John, Smith, Home, 123 test, Sebastopol, California, 12345, Home 1-800-123-4567, Personal john.smith@gmail.com 我已经缩进/隔开了源XML文件和相关的XSL模板,以使其更易于阅读和
Friend, John, Smith, Home,
123 test,
Sebastopol,
California,
12345,
Home 1-800-123-4567, Personal john.smith@gmail.com
我已经缩进/隔开了源XML文件和相关的XSL模板,以使其更易于阅读和开发,但所有这些额外的空白都会进入输出中。XML本身在节点内部没有额外的空白,只是在节点外部进行格式化,XSLT也是如此
为了使CSV文件有效,每个条目都需要在自己的行上,而不是分开。除了从XML和XSLT中去除所有额外的空白(使它们成为一行长代码),还有其他方法去除输出中的空白吗
编辑:
下面是一个小XML示例:
<PHONEBOOK>
<LISTING>
<FIRST>John</FIRST>
<LAST>Smith</LAST>
<ADDRESS TYPE="Home">
<STREET>123 test</STREET>
<CITY>Sebastopol</CITY>
<STATE>California</STATE>
<ZIP>12345</ZIP>
</ADDRESS>
<PHONE>1-800-123-4567</PHONE>
<EMAIL>john.smith@gmail.com</EMAIL>
<RELATION>Friend</RELATION>
</LISTING>
</PHONEBOOK>
约翰
史密斯
123试验
塞巴斯托波尔
加利福尼亚
12345
1-800-123-4567
厕所。smith@gmail.com
朋友
下面是XSLT:
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:for-each select="//LISTING">
<xsl:value-of select="RELATION" /><xsl:text>, </xsl:text>
<xsl:value-of select="FIRST" /><xsl:text>, </xsl:text>
<xsl:value-of select="LAST" /><xsl:text>, </xsl:text>
<xsl:if test="ADDRESS">
<xsl:for-each select="ADDRESS">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" />,
</xsl:when>
<xsl:otherwise>
<xsl:text>Home </xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="STREET" />,
<xsl:value-of select="CITY" />,
<xsl:value-of select="STATE" />,
<xsl:value-of select="ZIP" />,
</xsl:for-each>
</xsl:if>
<xsl:for-each select="PHONE">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" />
</xsl:when>
<xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="." /><xsl:text >, </xsl:text>
</xsl:for-each>
<xsl:if test="EMAIL">
<xsl:for-each select="EMAIL">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" /><xsl:text > </xsl:text>
</xsl:when>
<xsl:otherwise><xsl:text >Personal </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="." /><xsl:text >, </xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
,
,
,
,
家
,
,
,
,
家
,
个人的
,
默认情况下,XSLT模板设置了
,这将在输出中保留空白。您可以添加
来告诉它
删除空白的位置
您可能还需要包含规范化空间指令,如下所示:
<xsl:template match="text()"><xsl:value-of select="normalize-space(.)"/></xsl:template>
这里是一个。关于删除制表符但保留单独的行,我尝试了以下XSLT1.0方法,效果相当不错。版本1.0或2.0的使用在很大程度上取决于所使用的平台。看起来.NET技术仍然依赖于XSLT1.0,因此您只能使用非常混乱的模板(见下文)。如果您使用的是Java或其他东西,请参考下面列出的更干净的XSLT2.0方法 这些示例旨在由您扩展以满足您的特定需求。我在这里使用选项卡作为示例,但这应该足够通用,可以扩展 XML:
在XSLT中,默认情况下保留空白,因为它很可能是相关数据 防止输出中出现不需要的空白的最佳方法是首先不要创建空白。不要做:
<xsl:template match="foo">
foo
</xsl:template>
样式表中的空白将被忽略,只要它仅出现在XML元素之间。简而言之:不要在XSLT代码中的任何地方使用“裸”文本,始终将其包含在元素中
此外,使用非特定的:
<xsl:apply-templates />
所有文本节点现在都被禁用,必须显式创建文本输出:
<xsl:value-of select="data" />
但是要小心,因为函数会规范化字符串中的任何空白,例如“·value·1·”
将变成“value·1”
此外,您还可以使用
和
元素,尽管这通常不是必需的(我个人更喜欢如上所述的显式空白处理)。其他人已经指出了一般问题。样式表的一个具体问题是您忘记了逗号的
:
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" />,
</xsl:when>
<xsl:otherwise>Home </xsl:otherwise>
</xsl:choose>
<xsl:value-of select="STREET" />,
<xsl:value-of select="CITY" />,
<xsl:value-of select="STATE" />,
<xsl:value-of select="ZIP" />,
,
家
,
,
,
,
这使得每个逗号后面的空格都很重要,因此它最终会出现在输出中。如果将每个逗号都括在
中,问题就会消失
另外,去掉
禁用输出转义
。它在这里没有任何作用,因为您没有输出XML。在xslt中添加一个模板
<xsl:template match="text()"/>
我之前的答案是错误的,所有逗号必须通过标签“text”输出
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/PHONEBOOK">
<xsl:for-each select="LISTING">
<xsl:value-of select="RELATION" /><xsl:text>, </xsl:text>
<xsl:value-of select="FIRST" /><xsl:text>, </xsl:text>
<xsl:value-of select="LAST" /><xsl:text>, </xsl:text>
<xsl:for-each select="ADDRESS">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" /><xsl:text>,</xsl:text>
</xsl:when>
<xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="STREET/text()" /><xsl:text>,</xsl:text>
<xsl:value-of select="CITY/text()" /><xsl:text>,</xsl:text>
<xsl:value-of select="STATE/text()" /><xsl:text>,</xsl:text>
<xsl:value-of select="ZIP/text()" /><xsl:text>,</xsl:text>
</xsl:for-each>
<xsl:for-each select="PHONE">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" />
</xsl:when>
<xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="." /><xsl:text >, </xsl:text>
</xsl:for-each>
<xsl:if test="EMAIL">
<xsl:for-each select="EMAIL">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" /><xsl:text > </xsl:text>
</xsl:when>
<xsl:otherwise><xsl:text >Personal </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="." /><xsl:text >, </xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()|@*">
<xsl:text>-</xsl:text>
</xsl:template>
</xsl:stylesheet>
,
,
,
,
家
,
,
,
,
家
,
个人的
,
-
通过删除下面的行来修改我们用来格式化原始xml文件的代码将删除导出excel中添加的额外空白
当使用缩进属性设置格式时,系统会添加额外的空白
与格式化xml相关的注释行(如第行下方),然后重试
xmlWriter.Formatting = System.Xml.Formatting.Indented;
这个答案可能不是问题的直接答案。但是解决这个问题的一般方法。创建模板规则:
<xsl:template name="strip-space">
<xsl:param name="data"/>
<xsl:value-of select="normalize-space($data)"/>
</xsl:template>
现在是样式表:
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:apply-templates mode="t1"/>
<xsl:text>
</xsl:text>
<xsl:apply-templates mode="t2"/>
</xsl:template>
<xsl:template match="*" mode="t1">
<xsl:text>{</xsl:text>
<xsl:value-of select="local-name()"/>
<xsl:call-template name="strip-space">
<xsl:with-param name="data">
<xsl:apply-templates mode="t1"/>
</xsl:with-param>
</xsl:call-template>
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template match="*" mode="t2">
<xsl:text>{</xsl:text>
<xsl:value-of select="local-name()"/>
<xsl:value-of select="."/>
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template name="strip-space">
<xsl:param name="data"/>
<xsl:value-of select="normalize-space($data)"/>
</xsl:template>
</xsl:stylesheet>
输出描述了
@mode=“t1”
(
方法)与@mode=“t2”
(xsl:call-template
方法)的不同之处。希望这对某人有所帮助。为什么在每个
上都使用禁用输出转义?对于
,您不需要它。来自XSLT1.0规范:“文本输出方法忽略禁用输出转义属性,因为它不执行任何输出转义。”W3!=W3参考,W3参考就在这里->为什么?怎么用?谢谢您的回答,但请随时提供更多信息。
<xsl:value-of select="normalize-space(data)" />
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" />,
</xsl:when>
<xsl:otherwise>Home </xsl:otherwise>
</xsl:choose>
<xsl:value-of select="STREET" />,
<xsl:value-of select="CITY" />,
<xsl:value-of select="STATE" />,
<xsl:value-of select="ZIP" />,
<xsl:template match="text()"/>
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/PHONEBOOK">
<xsl:for-each select="LISTING">
<xsl:value-of select="RELATION" /><xsl:text>, </xsl:text>
<xsl:value-of select="FIRST" /><xsl:text>, </xsl:text>
<xsl:value-of select="LAST" /><xsl:text>, </xsl:text>
<xsl:for-each select="ADDRESS">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" /><xsl:text>,</xsl:text>
</xsl:when>
<xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="STREET/text()" /><xsl:text>,</xsl:text>
<xsl:value-of select="CITY/text()" /><xsl:text>,</xsl:text>
<xsl:value-of select="STATE/text()" /><xsl:text>,</xsl:text>
<xsl:value-of select="ZIP/text()" /><xsl:text>,</xsl:text>
</xsl:for-each>
<xsl:for-each select="PHONE">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" />
</xsl:when>
<xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="." /><xsl:text >, </xsl:text>
</xsl:for-each>
<xsl:if test="EMAIL">
<xsl:for-each select="EMAIL">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" /><xsl:text > </xsl:text>
</xsl:when>
<xsl:otherwise><xsl:text >Personal </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="." /><xsl:text >, </xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()|@*">
<xsl:text>-</xsl:text>
</xsl:template>
</xsl:stylesheet>
xmlWriter.Formatting = System.Xml.Formatting.Indented;
<xsl:template name="strip-space">
<xsl:param name="data"/>
<xsl:value-of select="normalize-space($data)"/>
</xsl:template>
<xsl:template match="my-element">
<xsl:call-template name="strip-space">
<xsl:with-param name="data">
<xsl:apply-templates/>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<?xml version="1.0" encoding="UTF-8"?>
<test>
<my-element>
<e1>some text</e1> <e2>some other text</e2> <e3>some other text</e3>
</my-element>
</test>
{test{my-element{e1some text} {e2some other text} {e3some other text}}}
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:apply-templates mode="t1"/>
<xsl:text>
</xsl:text>
<xsl:apply-templates mode="t2"/>
</xsl:template>
<xsl:template match="*" mode="t1">
<xsl:text>{</xsl:text>
<xsl:value-of select="local-name()"/>
<xsl:call-template name="strip-space">
<xsl:with-param name="data">
<xsl:apply-templates mode="t1"/>
</xsl:with-param>
</xsl:call-template>
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template match="*" mode="t2">
<xsl:text>{</xsl:text>
<xsl:value-of select="local-name()"/>
<xsl:value-of select="."/>
<xsl:text>}</xsl:text>
</xsl:template>
<xsl:template name="strip-space">
<xsl:param name="data"/>
<xsl:value-of select="normalize-space($data)"/>
</xsl:template>
</xsl:stylesheet>
{test{my-element{e1some text} {e2some other text} {e3some other text}}}
{test
some text some other text some other text
}