谁能解释下面的 xsl 是如何工作的?
Posted
技术标签:
【中文标题】谁能解释下面的 xsl 是如何工作的?【英文标题】:Can anyone explain how does the below xsl works? 【发布时间】:2021-09-27 01:14:31 【问题描述】:谁能用一个例子解释一下下面的 xsl 是如何工作的?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Remove empty elements or attributes -->
<xsl:template match="@*|node()">
<xsl:if test=". != '' or ./@* != ''">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
当我将上面的 xsl 用于下面的未缩进的 xml 时(注意它在下面显示缩进但认为它没有缩进。输入文本框不允许我放置未缩进的 xml):
<Book Edition="1234" Type="Novel" TimeStamp="2021-07-09T14:02:55-05:00" Version="1.003">
<BOS>
<LIB>
<RequestorID ID="XXX" Type="10"/>
</LIB>
</BOS>
<Sections>
<Section CreateDateTime="2021-07-03T11:21:43-05:00" CreatorID="XXX" Status="Read">
<UniqueID ID="443791" Type="10"/>
<Chapters>
<Chapter>
<Paragraphs>
<Paragraph NumberOfUnits="10" Lines="100">
<Rates>
<Rate EffectiveDate="2021-12-12" ExpireDate="2021-12-13" RateTimeUnit="Day" UnitMultiplier="1">
<Base AmountBeforeTax="145.90" CurrencyCode="USD"/>
</Rate>
</Rates>
</Paragraph>
</Paragraphs>
<Readers>
<Reader Age="10" Count="1"/>
</Readers>
<TimeSpan End="2021-12-13" Start="2021-12-12"/>
<BasicInfo BookCode="1310"/>
</Chapter>
</Chapters>
<Authors>
<Author AuthorRPH="1">
<Profiles>
<ProfileInfo>
<UniqueID ID="44379" Type="1"/>
<Profile ProfileType="1">
<Author>
<PersonName>
<GivenName>TEST</GivenName>
<Surname>TEST</Surname>
</PersonName>
<Telephone PhoneNumber="0"/>
<Email>test@test.com</Email>
<Address Type="H">
<AddressLine>123 MAIN ST</AddressLine>
</Address>
</Author>
</Profile>
</ProfileInfo>
</Profiles>
</Author>
</Authors>
<GlobalInfo>
<ReadIds>
<ReadId ReadID_Source="ZZZ" ReadID_Type="10" ReadID_Value="1234"/>
</ReadIds>
</GlobalInfo>
</Section>
</Sections>
</Book>
然后我得到以下输出:
<Book Edition="1234" Type="Novel" TimeStamp="2021-07-09T14:02:55-05:00" Version="1.003">
<BOS>
<LIB>
<RequestorID ID="XXX" Type="10"/>
</LIB>
</BOS>
<Sections>
<Section CreateDateTime="2021-07-03T11:21:43-05:00" CreatorID="XXX" Status="Read">
<UniqueID ID="443791" Type="10"/>
<Authors>
<Author AuthorRPH="1">
<Profiles>
<ProfileInfo>
<UniqueID ID="44379" Type="1"/>
<Profile ProfileType="1">
<Author>
<PersonName>
<GivenName>TEST</GivenName>
<Surname>TEST</Surname>
</PersonName>
<Telephone PhoneNumber="0"/>
<Email>test@test.com</Email>
<Address Type="H">
<AddressLine>123 MAIN ST</AddressLine>
</Address>
</Author>
</Profile>
</ProfileInfo>
</Profiles>
</Author>
</Authors>
</Section>
</Sections>
</Book>
如上所示,它会删除章节标签和全局信息标签内的所有内容
但是如果我使用上面的 xsl 用于下面的缩进的 xml:
<Book Edition="1234" Type="Novel" TimeStamp="2021-07-09T14:02:55-05:00" Version="1.003">
<POS>
<Source>
<RequestorID ID="XXX" Type="10"/>
</Source>
</POS>
<Sections>
<Section CreateDateTime="2021-07-03T11:21:43-05:00" CreatorID="XXX" Status="Read">
<UniqueID ID="443791" Type="10"/>
<Chapters>
<Chapter>
<Paragraphs>
<Paragraph NumberOfUnits="10" Lines="100">
<Rates>
<Rate EffectiveDate="2021-12-12" ExpireDate="2021-12-13" RateTimeUnit="Day" UnitMultiplier="1">
<Base AmountBeforeTax="145.90" CurrencyCode="USD"/>
</Rate>
</Rates>
</Paragraph>
</Paragraphs>
<Readers>
<Reader Age="10" Count="1"/>
</Readers>
<TimeSpan End="2021-12-13" Start="2021-12-12"/>
<BasicInfo BookCode="1310"/>
</Chapter>
</Chapters>
<Authors>
<Author AuthorRPH="1">
<Profiles>
<ProfileInfo>
<UniqueID ID="44379" Type="1"/>
<Profile ProfileType="1">
<Author>
<PersonName>
<GivenName>TEST</GivenName>
<Surname>TEST</Surname>
</PersonName>
<Telephone PhoneNumber="0"/>
<Email>test@test.com</Email>
<Address Type="H">
<AddressLine>123 MAIN ST</AddressLine>
</Address>
</Author>
</Profile>
</ProfileInfo>
</Profiles>
</Author>
</Authors>
<GlobalInfo>
<ReadIds>
<ReadId ReadID_Source="ZZZ" ReadID_Type="10" ReadID_Value="1234"/>
</ReadIds>
</GlobalInfo>
</Section>
</Sections>
</Book>
然后我得到正确的输出:
<Book Edition="1234" Type="Novel" TimeStamp="2021-07-09T14:02:55-05:00" Version="1.003">
<BOS>
<LIB>
<RequestorID ID="XXX" Type="10"/>
</LIB>
</BOS>
<Sections>
<Section CreateDateTime="2021-07-03T11:21:43-05:00" CreatorID="XXX" Status="Read">
<UniqueID ID="443791" Type="10"/>
<Chapters>
<Chapter>
<Paragraphs>
<Paragraph NumberOfUnits="10" Lines="100">
<Rates>
<Rate EffectiveDate="2021-12-12" ExpireDate="2021-12-13" RateTimeUnit="Day" UnitMultiplier="1">
<Base AmountBeforeTax="145.90" CurrencyCode="USD"/>
</Rate>
</Rates>
</Paragraph>
</Paragraphs>
<Readers>
<Reader Age="10" Count="1"/>
</Readers>
<TimeSpan End="2021-12-13" Start="2021-12-12"/>
<BasicInfo BookCode="1310"/>
</Chapter>
</Chapters>
<Authors>
<Author AuthorRPH="1">
<Profiles>
<ProfileInfo>
<UniqueID ID="44379" Type="1"/>
<Profile ProfileType="1">
<Author>
<PersonName>
<GivenName>TEST</GivenName>
<Surname>TEST</Surname>
</PersonName>
<Telephone PhoneNumber="0"/>
<Email>test@test.com</Email>
<Address Type="H">
<AddressLine>123 MAIN ST</AddressLine>
</Address>
</Author>
</Profile>
</ProfileInfo>
</Profiles>
</Author>
</Authors>
<GlobalInfo>
<ReadIds>
<ReadId ReadID_Source="ZZZ" ReadID_Type="10"
ReadID_Value="1234"/>
</ReadIds>
</GlobalInfo>
</Section>
</Sections>
</Book>
谁能解释一下xmls是否相同,为什么缩进会给出不同的输出?适当的缩进会影响 xsl 转换吗?
【问题讨论】:
它执行identity transform 并为空元素添加了过滤器。 【参考方案1】:测试中的 XPath 表达式 . != '' or ./@* != ''
的行为可能与您预期的不同。 XPath 1.0 的规范(通常与 XSLT 1.0 一起使用),如 version="1.0"
所示,https://www.w3.org/TR/1999/REC-xpath-19991116/#dt-string-value
对于每种类型的节点,都有一种确定字符串值的方法 对于该类型的节点。对于某些类型的节点,字符串值是 节点的一部分;对于其他类型的节点,字符串值为 根据后代节点的字符串值计算。
在“5.2 元素节点”一节中
元素节点的字符串值是 元素节点的所有文本节点后代的字符串值 按文档顺序。
因此,对于普通的非缩进源元素,字符串转换涉及递归下降到元素并获取它们的值(忽略属性)。在您的情况下,对于一个也没有属性的元素,如果它没有任何像 <elem>value</elem>
这样的值的元素,则整个子树将被消除(即不复制到输出)。
使用缩进源,您还有代表节点之间空白的节点。 (XPath 不知道空格与您无关,并假定混合内容。)这会导致具有(缩进)子元素的元素的字符串转换在字符串的结果中(至少)具有该空格转换,使. != ''
XPath 表达式为 false。
我希望,这可以解释结果的差异取决于源代码中的缩进。
您可能想查看https://www.w3.org/TR/1999/REC-xpath-19991116/#function-normalize-space 以调整转换结果。请注意,如果这些都可以是空白,这也可能会影响对“真实值”的尊重。
编辑:根据您想要实现的目标,您可能会考虑使用 xsl:strip-space 让 XSLT 处理器消除空白。
【讨论】:
两个标签之间的空格是否被视为文本节点?或者,如果每个标签都在新行上,如下所示,那么新行是否被视为文本节点? 或 是的,两个标签之间的空白被映射到一个文本节点。它包含所有字符,即不仅包含换行符,还包含制表符和空格。如果您使用xsl:strip-whitespace,这些文本节点将在处理之前被消除。【参考方案2】:代码有一个匹配所有元素、文本、注释、处理指令和属性节点的模板规则。如果节点具有非空字符串值,或者具有非空字符串值的属性,则它会浅拷贝节点并递归处理其属性和子节点。
总体效果是复制整个文档,除了没有内容且没有非空属性的元素(例如<br/>
)- 加上一些其他例外,例如空 cmets。
【讨论】:
以上是关于谁能解释下面的 xsl 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章