Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XSLT-从模板中删除空白_Xml_Xslt - Fatal编程技术网

Xml XSLT-从模板中删除空白

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模板,以使其更易于阅读和

我正在使用XML存储一个小的联系人列表,并试图编写一个XSL模板,将其转换为CSV文件。我遇到的问题是输出中的空白

输出:

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>&#10;&#13;</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>&#10;&#13;</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>&#xa;</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>&#10;&#13;</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>&#xa;</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

}