使用 XSLT 将 XML 转换为 XML 删除前导空格和零

Posted

技术标签:

【中文标题】使用 XSLT 将 XML 转换为 XML 删除前导空格和零【英文标题】:Transform XML to XML using XSLT removing leading spaces and zeroes 【发布时间】:2019-05-22 17:03:47 【问题描述】:

请帮助:尝试通过删除前导零和空格来转换 XML;以下 XSLT 不适用于我:

    <?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="xalan://org.apache.commons.lang.StringUtils" 
exclude-result-prefixes="str">
<xsl:output method="xml" indent="yes" />

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

<xsl:template match="h1">
    <h1>
            <xsl:variable name="leadingZeroRemoved">
            <xsl:call-template name="removeLeadingZero">
                <xsl:with-param name="text" select="." />
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="leadingSpaceRemoved">
            <xsl:call-template name="removeLeadingSpace">
                <xsl:with-param name="text" select="$leadingZeroRemoved" />
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="trailingSpaceRemoved">
            <xsl:call-template name="removeTrailingSpace">
                <xsl:with-param name="text" select="$leadingSpaceRemoved" />
            </xsl:call-template>
        </xsl:variable>

        <xsl:value-of select="$trailingSpaceRemoved" />
    </h1>
</xsl:template>

<xsl:template name="removeLeadingZero">
    <xsl:param name="text" />

    <xsl:variable name="h1" select="$text" />
    <xsl:choose>
 <xsl:when test="starts-with($text,'0')">
            <xsl:call-template name="removeLeadingZero">
                <xsl:with-param name="text"
                    select="substring-after($text,'0')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>




<xsl:template name="removeLeadingSpace">
    <xsl:param name="text" />

    <xsl:variable name="h1" select="$text" />
    <xsl:choose>
        <xsl:when test="starts-with($h1,' ')">
            <xsl:call-template name="removeLeadingSpace">
                <xsl:with-param name="text" select="substring-after($h1,' ')" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$h1" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="removeTrailingSpace">
    <xsl:param name="text" />

    <xsl:variable name="h1" select="$text" />
    <xsl:choose>
        <xsl:when test="str:ends-with($h1,' ')">
            <xsl:call-template name="removeTrailingSpace">
                <xsl:with-param name="text" select="str:substringBeforeLast($h1,' ')" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$h1" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>

我生成的输入和输出是:

$  cat newXMLTEST.FILE
<?xml version="1.0" encoding="UTF-8"?><School>
<Student>
<Id_Numer>0000034</Id_Numer>
<Name>   David</Name>
<Tot_Marks>000000100</Tot_Marks>
<Last_YearTot_Marks>000000000</Last_YearTot_Marks>
<Fee_Paid>000043.01</Fee_Paid>
</Student>
</School>
$  cat ne.xml
<?xml version="1.0" encoding="UTF-8"?>
<School>
<Student>
<Id_Numer>0000034</Id_Numer>
<Name>   David</Name>
<Tot_Marks>000000100</Tot_Marks>
<Last_YearTot_Marks>000000000</Last_YearTot_Marks>
<Fee_Paid>000043.01</Fee_Paid>
</Student>
</School> 

但我正在寻找如下内容:

<?xml version="1.0" encoding="UTF-8"?>
<School>
<Student>
<Id_Numer>34</Id_Numer>
<Name>David</Name>
<Tot_Marks>100</Tot_Marks>
<Last_YearTot_Marks>0</Last_YearTot_Marks>
<Fee_Paid>43.01</Fee_Paid>
</Student>
</School>

我是 XSLT 和 Xpath 的初学者。我修改了一些 XSLT 的在线版本并尝试使用它。提前致谢。

【问题讨论】:

你能澄清你所说的“它不工作”是什么意思吗?如果正确调用,模板将删除前导空格(尽管例如,如果有换行符作为第一个字符,则不会)。显示一些示例输入和您当前获得的输出(以及您所期望的)可能会有所帮助。谢谢! 【参考方案1】:

鉴于您的意见:

XML

<?xml version="1.0" encoding="UTF-8"?>
<School>
<Student>
<Id_Numer>0000034</Id_Numer>
<Name>   David</Name>
<Tot_Marks>000000100</Tot_Marks>
<Last_YearTot_Marks>000000000</Last_YearTot_Marks>
<Fee_Paid>000043.01</Fee_Paid>
</Student>
</School>

以下样式表:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="Name">
    <xsl:copy>
        <xsl:value-of select="normalize-space(.)"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Id_Numer | Tot_Marks | Last_YearTot_Marks | Fee_Paid">
    <xsl:copy>
        <xsl:value-of select="number(.)"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

将产生:

结果

<?xml version="1.0" encoding="UTF-8"?>
<School>
  <Student>
    <Id_Numer>34</Id_Numer>
    <Name>David</Name>
    <Tot_Marks>100</Tot_Marks>
    <Last_YearTot_Marks>0</Last_YearTot_Marks>
    <Fee_Paid>43.01</Fee_Paid>
  </Student>
</School>

补充:

要使其更通用,请尝试:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="text()">
    <xsl:value-of select="normalize-space(.)"/>
</xsl:template>

<xsl:template match="text()[number(.)=number(.)]">
    <xsl:value-of select="number(.)"/>
</xsl:template>

</xsl:stylesheet>

【讨论】:

谢谢..但是我输入的xml标签不是恒定的..我有很多输入xml..我没有任何控制...我正在寻找动态的东西..我可以tweek 在你的 xslt 上放一些东西 .. thx !我的意思是说 XML 并不总是相同的,所以它并不总是 Id_Numer | Tot_Marks | Last_YearTot_Marks | Fee_Paid @user3342678 查看我的答案的补充。 谢谢先生。它帮助了我.. 我试图规范化 Xmls 并使用 unix diff 比较差异,这样我就可以找到我需要的那些。我的另一个问题是,如果缺少结束标记,我们是否有损坏的 xml,在上面的示例中,如果 结束标记以 > 的形式出现 .. 是否有可能我可以要求 xsl 继续没有抛出异常?现在我得到了预期的结束标签异常。 XSLT 将只处理格式良好的 XML 文档。【参考方案2】:

如果要删除元素之间的空格,请在样式表元素级别添加以下指令:

<xsl:strip-space elements="*" />

如果要删除text()节点的前导和尾随空格,请添加以下模板:

<xsl:template match="text()">
    <xsl:value-of select="normalize-space(.)" />
</xsl:template>

【讨论】:

以上是关于使用 XSLT 将 XML 转换为 XML 删除前导空格和零的主要内容,如果未能解决你的问题,请参考以下文章

使用XSLT将XML转换为csv

使用 XSLT 进行空前缀转换的 XML [重复]

XSLT 转换从混合内容中删除 HTML 元素

使用 Xslt 将 XML 转换为 XML

使用带有条件的 XSLT 将 XML 转换为 XML

使用 XSLT 将 XML 元素转换为 XML 属性