我是xslt主题的新手,有一个我自己无法解决的问题。 这是我的xml文件的示例:
<node>
<failure><![CDATA[
some useless information.
CRS urn:ogc:def:crs:EPSG::25830 not defined.
CRS urn:ogc:def:crs:EPSG::25833 not possible.
CRS urn:ogc:def:crs:EPSG::25830 not defined.
some useless information.]]>
</failure>
</node>
主要问题是信息站在CDATA块中,并且混合了许多不同的信息。我找到了一种方法来解决它们,但只是作为一个字符串值无法区分排序。
我需要一种方法来提取符合模式的元素:“CRS [-unknown-] [id]而不是[result]”
我想要的是这样的:
<failure>
<CRS>
<id> urn:ogc:def:crs:EPSG::25830 </id>
<result> not defined </result>
</CRS>
<CRS>
<id> urn:ogc:def:crs:EPSG::25833 </id>
<result> not posible </result>
</CRS>
<CRS>
<id> urn:ogc:def:crs:EPSG::25830 </id>
<result> not defined </result>
</CRS>
</failure>
有人可以帮助我或者解决类似问题吗?
答案 0 :(得分:0)
XSLT 2.0具有xsl:analyze-string
,专为此任务而设计,因此,如果可能,我建议您升级到2.0处理器,例如Saxon:
<xsl:template match="node">
<failure>
<xsl:analyze-string select="failure"
regex="^\s*CRS\s*(\S+)\s*(not\s*.*)$" flags="m">
<xsl:matching-substring>
<CRS>
<id><xsl:value-of select="regex-group(1)" /></id>
<result><xsl:value-of select="normalize-space(regex-group(2))" /></result>
</CRS>
</xsl:matching-substring>
</xsl:analyze-string>
</failure>
</xsl:template>
XSLT 1.0中的字符串操作工具相比之下非常有限,并且由于XSLT是一种没有可更新变量的函数式语言,因此您必须编写某种可靠的递归call-template
逻辑来分割文本分成几行,然后使用substring-before
和substring-after
依次从每行中提取相关位。
<xsl:template name="each-line">
<xsl:param name="val" />
<!-- pull out everything before the first newline and normalize (trim leading
and trailing whitespace and squash internal whitespace to a single space
character -->
<xsl:variable name="firstLine"
select="normalize-space(substring-before($val, ' '))" />
<!-- pull out everything after the first newline -->
<xsl:variable name="rest" select="substring-after($val, ' ')" />
<xsl:if test="$firstLine">
<xsl:call-template name="process-line">
<xsl:with-param name="line" select="$firstLine" />
</xsl:call-template>
</xsl:if>
<!-- if there are still some non-empty lines left then process them recursively -->
<xsl:if test="normalize-space($rest)">
<xsl:call-template name="each-line">
<xsl:with-param name="val" select="$rest" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="process-line">
<xsl:param name="line" />
<xsl:if test="starts-with($line, 'CRS ') and contains($line, ' not ')">
<!-- here $line will be something like
"CRS urn:ogc:def:crs:EPSG::25830 not defined." -->
<CRS>
<!-- ID is everything between the first and second spaces -->
<id><xsl:value-of select="substring-before(substring-after($line, ' '), ' ')" /></id>
<!-- result is everything after the second space -->
<result><xsl:value-of select="substring-after(substring-after($line, ' '), ' ')" /></result>
</CRS>
</xsl:if>
</xsl:template>
您可以使用类似
的构造来调用此逻辑<xsl:template match="node">
<failure>
<xsl:call-template name="each-line">
<xsl:with-param name="val" select="failure" />
</xsl:call-template>
</failure>
</xsl:template>