我有这个XML:
<property id="1011">
<leasehold>No</leasehold>
<freehold>Yes</freehold>
<propertyTypes>
<propertyType>RESIDENTIAL</propertyType>
</propertyTypes>
</property>
我想创建一个xpath语句,它与下面嵌套的if-else伪代码块相同。
if( propertyTypes/propertyType == 'RESIDENTIAL') {
if( leasehold == 'Yes' ){
return 'Rent'
} else
return 'Buy'
}
} else {
if( leasehold == 'Yes' ){
return 'Leasehold'
} else
return 'Freehold'
}
}
我见过Becker的方法但我无法真正遵循它。 XPath真的不是我的强项。
答案 0 :(得分:21)
<强>予。在XPath 2.0中,只需将其转换为:
if(/*/propertyTypes/propertyType = 'RESIDENTIAL')
then
(if(/*/leasehold='Yes')
then 'Rent'
else 'Buy'
)
else
if(/*/leasehold='Yes')
then 'Leasehold'
else 'Freehold'
基于XSLT 2.0的验证:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:sequence select=
"if(/*/propertyTypes/propertyType = 'RESIDENTIAL')
then
(if(/*/leasehold='Yes')
then 'Rent'
else 'Buy'
)
else
if(/*/leasehold='Yes')
then 'Leasehold'
else 'Freehold'
"/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<property id="1011">
<leasehold>No</leasehold>
<freehold>Yes</freehold>
<propertyTypes>
<propertyType>RESIDENTIAL</propertyType>
</propertyTypes>
</property>
评估XPath表达式并将此评估结果复制到输出中:
Buy
<强> II。 XPath 1.0解决方案
在XPath 1.0中,没有if
运算符。
条件语句仍然可以使用单个XPath 1.0表达式实现,但这更棘手,表达式可能不太容易阅读和理解。
这是一种通用方式(由Jeni Tennison首先提出),当条件$stringA
为$cond
并生成true()
时生成$stringB
:
concat(substring($stringA, 1 div $cond), substring($stringB, 1 div not($cond)))
此公式的主要成就之一是它适用于任何长度的字符串,不需要指定长度。
<强>解释强>:
这里我们使用的事实是:
number(true()) = 1
和
number(false()) = 0
那个
1 div 0 = Infinity
因此,如果$cond
为false
,则concat()
的第一个参数为:
substring($stringA, Infinity)
这是空字符串,因为$stringA
的长度有限。
另一方面,如果$cond
为true()
,则上面concat()
的第一个参数为:
sibstring($stringA, 1)
只是$stringA
。
因此,根据$cond
的值,上面concat()
的两个参数中只有一个是非空字符串(分别为$stringA
或$stringB
)。
将此通用公式应用于特定问题,我们可以将大条件表达式的前半部分转换为:
concat(
substring('rent',
1 div boolean(/*[leasehold='Yes'
and
propertyTypes/propertyType = 'RESIDENTIAL'
]
)
),
substring('buy',
1 div not(/*[leasehold='Yes'
and
propertyTypes/propertyType = 'RESIDENTIAL'
]
)
)
)
这可以让您了解如何将整个条件表达式转换为单个XPath 1.0表达式。
基于XSLT 1.0的验证:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select=
"concat(
substring('rent',
1 div boolean(/*[leasehold='Yes'
and
propertyTypes/propertyType = 'RESIDENTIAL'
]
)
),
substring('buy',
1 div not(/*[leasehold='Yes'
and
propertyTypes/propertyType = 'RESIDENTIAL'
]
)
)
)
"/>
</xsl:template>
</xsl:stylesheet>
当在提供的XML文档(上面)上应用此转换时,将评估XPath表达式并将此评估的结果复制到输出:
buy
请注意:
如果您决定使用长度与原始字符串不同的其他字符串替换特定字符串,则只需在上面的XPath 1.0表达式中替换这些字符串,您就不必担心指定任何长度。
答案 1 :(得分:2)
Becker的数据处理方法如下:
concat(substring('Rent', 1 div boolean(propertyTypes/propertyType ="RESIDENTIAL" and leasehold="Yes")),
substring('Buy', 1 div boolean(propertyTypes/propertyType ="RESIDENTIAL" and leasehold="No")),
substring('Leasehold', 1 div boolean(propertyTypes/propertyType!="RESIDENTIAL" and leasehold="Yes")),
substring('Freehold', 1 div boolean(propertyTypes/propertyType!="RESIDENTIAL" and leasehold="No")))
答案 2 :(得分:1)
今天花了一整天,但对我来说这适用于Xpath 1.0:
concat(
substring(properties/property[@name="Headline"], 1, string-length(properties/property[@name="Headline"]) * 1),
substring(properties/property[@name="Name"], 1, not(number(string-length(properties/property[@name="Headline"]))) * string-length(properties/property[@name="Name"]))
)
答案 3 :(得分:0)
试试这个
if (condition)
then
if (condition) stmnt
else stmnt
else
if (condition) stmnt
else stmnt