我有一个以下模式的xml
<?xml version="1.0" encoding="UTF-8"?>
<Person>
<FirstName>Ahmed</FirstName>
<MiddleName/>
<LastName>Aboulnaga</LastName>
<CompanyInfo>
<CompanyName>IPN Web</CompanyName>
<Title/>
<Role></Role>
<Department>
</Department>
</CompanyInfo>
</Person>
我尝试删除空标记时使用了以下xslt(来自论坛)
<xsl:template match="@*|node()">
<xsl:if test=". != '' or ./@* != ''">
<xsl:copy>
<xsl:copy-of select = "@*"/>
<xsl:apply-templates />
</xsl:copy>
</xsl:if>
使用的xslt成功删除了像
这样的标签<Title/>
<Role></Role>
...但是当空标签位于两行时失败,例如:
<Department>
</Department>
有没有解决这个问题?
答案 0 :(得分:13)
此转换根本不需要任何条件XSLT指令,并且不使用明确的优先级:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[not(@*|*|comment()|processing-instruction())
and normalize-space()=''
]"/>
</xsl:stylesheet>
应用于提供的XML文档:
<Person>
<FirstName>Ahmed</FirstName>
<MiddleName/>
<LastName>Aboulnaga</LastName>
<CompanyInfo>
<CompanyName>IPN Web</CompanyName>
<Title/>
<Role></Role>
<Department>
</Department>
</CompanyInfo>
</Person>
会产生想要的正确结果:
<Person>
<FirstName>Ahmed</FirstName>
<LastName>Aboulnaga</LastName>
<CompanyInfo>
<CompanyName>IPN Web</CompanyName>
</CompanyInfo>
</Person>
答案 1 :(得分:3)
<xsl:template match="@*|node()">
<xsl:if test="normalize-space(.) != '' or ./@* != ''">
<xsl:copy>
<xsl:copy-of select = "@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
答案 2 :(得分:2)
(..)有没有解决这个问题?
两行上的标记不是空标记。它是一个包含空格的标记(如新行和可能的某些空白字符)。 XPath 1.0函数normalize-space()
允许您规范化标记的内容通过剥离不需要的新行。
将功能应用于标记内容后,您可以检查空字符串。执行此操作的一种好方法是将XPath 1.0 boolean()
函数应用于标记内容。 如果内容为零长度字符串,则其结果为false 。
最后,您可以嵌入所有内容,稍微改变您的身份转换。您不需要xsl:if
说明或任何其他附加模板。
最终的转换将如下所示:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates
select="node()[boolean(normalize-space())]
|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
附加说明
您的xsl:if
指令当前也在检查空属性。以这种方式您实际上也删除了具有空属性的非强制标记。这听起来不像只是“删除空标签”。所以要小心,否则你的问题会遗漏一些细节,或者你使用的是不安全的代码。
答案 3 :(得分:1)
您的问题未明确。 空是什么意思? <outer>
在这里是空的吗?
<outer><inner/></outer>
无论如何,这是一种可能符合您账单的方法:
<xsl:template match="*[not(.//@*) and not( normalize-space() )]" priority="3"/>
请注意,您可能需要调整优先级以满足您的需求。
答案 4 :(得分:1)
根据我在网上发现的内容,这是最正确的答案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="*">
<xsl:if test=".!=''">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
答案 5 :(得分:1)
您可以使用以下xslt删除空标记/属性:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="node()">
<xsl:if test="normalize-space(string(.)) != ''
or count(@*[normalize-space(string(.)) != '']) > 0
or count(descendant::*[normalize-space(string(.)) != '']) > 0
or count(descendant::*/@*[normalize-space(string(.)) != '']) > 0">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="@*">
<xsl:if test="normalize-space(string(.)) != ''">
<xsl:copy>
<xsl:apply-templates select="@*" />
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>