XSLT:如何保留元素之间的空格?

时间:2016-04-09 19:00:05

标签: xml xslt xslt-2.0

我有一个新的要求,要使转换的XML更具可读性,即保留元素之间的cr,制表符和其他空格。

我似乎无法弄清楚如何保留空白。

有人可以帮忙吗?

XML文件

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
    </Fragment>
</Wix>

XSL文件:

  <?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet version="2.0" 
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:m="http://schemas.microsoft.com/wix/2006/wi">
  <xsl:preserve-space elements="*" />
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/m:Wix">
    <xsl:message>Matched Wix</xsl:message>
    <xsl:copy>
      <!-- Insert the new include processing instruction -->
      <xsl:processing-instruction name="include">
        <xsl:text>$(sys.CURRENTDIR)src/includes/globals.wxi </xsl:text>
      </xsl:processing-instruction>
      <!-- place the existing children into the output -->
      <xsl:apply-templates select="@* | *"/> 
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

当前输出:

<?xml version="1.0" encoding="UTF-8"?><Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"><?include $(sys.CURRENTDIR)src/includes\globals.wxi ?><Fragment>
    </Fragment></Wix>

期望输出

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <?include $(sys.CURRENTDIR)src/includes\globals.wxi ?>
    <Fragment>
    </Fragment>
</Wix>

3 个答案:

答案 0 :(得分:1)

通过在流程指令之前和之后添加以下文本,考虑使用换行符&#xa;和制表符实体&#9;。并确保将缩进输出标题添加到顶部:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
                  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                  xmlns:m="http://schemas.microsoft.com/wix/2006/wi">
  <xsl:output version="1.0" encoding="UTF-8" indent="yes" />
  <xsl:preserve-space elements="*" />

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/m:Wix">
    <xsl:message>Matched Wix</xsl:message>
    <xsl:copy>
      <xsl:text>&#xa; &#9;</xsl:text>      
      <!-- Insert the new include processing instruction -->
      <xsl:processing-instruction name="include">
        <xsl:text>$(sys.CURRENTDIR)src/includes/globals.wxi </xsl:text>
      </xsl:processing-instruction>
      <xsl:text>&#xa; &#9;</xsl:text>      
      <!-- place the existing children into the output -->
        <xsl:apply-templates select="@* | *"/>        
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

或者,使用多个非中断空格实体&#160;代替制表符,以便更精确地对齐:

<xsl:text>&#xa;&#160;&#160;&#160;&#160;</xsl:text>    

<强>输出

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <?include $(sys.CURRENTDIR)src/includes/globals.wxi?>
    <Fragment>
    </Fragment>
</Wix>

答案 1 :(得分:1)

输入中有三个空白文本节点:两个是Fragment元素的兄弟节点,另一个是Fragment元素的子节点。

前两个没有被复制到你的输出,因为m:Wix元素的模板忽略了它们:<xsl:apply-templates select="@* | *"/>只选择元素子元素,而不是文本节点子元素。

处理Fragment的空白文本内容,并保留在输出中。

现在:你在问题中说两件事:(a)你想让输出可读,(b)你想保留输入中的空白。我建议(b)不是实现(a)的最佳方式。实现(a)的最佳方法是忽略输入中存在的空白,并使用xsl:output indent="yes"在输出中添加新的空格。

但是,如果您确实要将输入中的空格复制到输出,则在处理元素的子元素时需要使用select="node()"而不是select="*"

答案 2 :(得分:0)

我的漂亮打印选择工具是xmlint。

xmllint --format old.xml > new.xml

但我确实看到你正在添加处理指令。所以需要xslt。

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:m="http://schemas.microsoft.com/wix/2006/wi"
    exclude-result-prefixes="m">

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:preserve-space elements="*" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="m:Wix">
        <xsl:message>Matched Wix</xsl:message>
        <Wix>

            <xsl:call-template name="CR"/>
            <xsl:call-template name="TAB"/>

            <!-- Insert the new include processing instruction -->
            <xsl:processing-instruction name="include">
                <xsl:text>$(sys.CURRENTDIR)src/includes/globals.wxi</xsl:text>
            </xsl:processing-instruction>

            <!-- place the existing children into the output -->
            <xsl:apply-templates/> 
        </Wix>
    </xsl:template>

    <xsl:template match="m:Fragment">
        <Fragment>
            <xsl:apply-templates/>
        </Fragment>
    </xsl:template>

    <xsl:template name="CR">
        <xsl:text>&#xa;</xsl:text>      
    </xsl:template>

    <xsl:template name="TAB">
        <xsl:text>&#9;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

如果您的真实XML变得更复杂,您可能需要先xmllint。然后做一个简单的xslt来添加处理指令。 Xmllint非常容易识别空格,xslt你必须把它烘烤。

相关问题