我的输入xml文件看起来像
<root>
<sub>
<element1 value="abc"/>
<element2 value="123"/>
</sub>
<sub1>
<element1 value="ert"/>
<element2 value="abc"/>
</sub1>
</root>
我需要一个XSLT函数,它在XML文件下面读取并从上面的文件中提取map / domain / instance / @ xpath中指定的xpath表达式值
<map>
<domain>
<instance xpath="root/sub/element1/@value" length="2"/>
</domain>
<domain>
<instance xpath="root/sub1/element2/@value" length="3"/>
</domain>
</map>
我需要一个xslt函数,它根据传入的xml文件检查为每个xpath表达式指定的长度。
如果长度不合适,则应该返回错误。
答案 0 :(得分:3)
这个XSLT 1.0样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="document">
<root>
<sub>
<element1 value="abc"/>
<element2 value="123"/>
</sub>
<sub1>
<element1 value="ert"/>
<element2 value="abc"/>
</sub1>
</root>
</xsl:variable>
<xsl:template match="map/domain/instance" name="walker">
<xsl:param name="path" select="@xpath"/>
<xsl:param name="context"
select="document('')/*/xsl:variable[@name='document']"/>
<xsl:choose>
<xsl:when test="contains($path,'/')">
<xsl:call-template name="walker">
<xsl:with-param name="path"
select="substring-after($path,'/')"/>
<xsl:with-param name="context"
select="$context/*[name()=substring-before($path,'/')]"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="starts-with($path,'@')">
<xsl:value-of select="concat(
string-length(
$context/attribute::*
[name()=substring($path,2)])
=@length,
'
')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(
string-length(
$context/*[name()=$path])
=@length,
'
')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
输出:
false
true
编辑: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"
xmlns:my="example.org">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="document">
<root>
<sub>
<element1 value="abc"/>
<element2 value="123"/>
</sub>
<sub1>
<element1 value="ert"/>
<element2 value="abc"/>
</sub1>
</root>
</xsl:variable>
<xsl:template match="map/domain/instance">
<xsl:sequence select="my:xpath(@xpath,$document)
/string(string-length() =
current()/@length)"/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:function name="my:xpath" as="item()*">
<xsl:param name="path" as="xs:string"/>
<xsl:param name="context" as="node()*"/>
<xsl:variable name="steps" as="item()*"
select="tokenize($path,'/')"/>
<xsl:variable name="this" as="item()*"
select="$context/(*[if ($steps[1]='*')
then true()
else name()=$steps[1]]|
@*[if ($steps[1]='@*')
then true()
else name() =
substring($steps[1],2)])"/>
<xsl:choose>
<xsl:when test="count($steps)>1">
<xsl:sequence
select="my:xpath(string-join($steps[position()!=1],
'/'),
$this)"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="$this"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
</xsl:stylesheet>
输出:
false
true
编辑2 :有点改进。现在,通过这个输入:
<map>
<domain>
<instance xpath="root/sub/element1/@*" length="2"/>
</domain>
<domain>
<instance xpath="root/sub/*/@value" length="3"/>
</domain>
</map>
输出:
false
true true