新手求助:如何使用XSLT转换XML文件格式并拆分XML内字符串
如何用XSLT转换XML格式并拆分字符串?
嘿,作为刚接触XML/XSLT的新手,别慌,我来一步步帮你搞定这两个需求——XML格式转换和字符串拆分。咱们结合你给出的示例XML来拆解:
首先先把你提供的示例补全(假设第二个persons节点结构和第一个一致):
<?xml version="1.0" encoding="utf-8"?> <root type="array"> <persons> <person_id>_:genid1</person_id> <type>http://www.w3.org/2000/01/rdf-schema#Datatype</type> <oneofs> <oneof>This is a very long string</oneof> </oneofs> </persons> <persons> <person_id>_:genid2</person_id> <type>http://www.w3.org/2000/01/rdf-schema#Datatype</type> <oneofs> <oneof>Another example string here</oneof> </oneofs> </persons> </root>
一、XML格式转换的基础实现
XSLT的核心是通过模板匹配定位XML节点,再输出你想要的结构。比如咱们想把上面的XML转换成更简洁的<people>根节点,每个人员用<person>包裹,只保留id和拆分后的字符串,那可以这么写XSLT:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 匹配根节点,输出新的根结构 --> <xsl:template match="/root"> <people> <!-- 遍历所有persons节点 --> <xsl:apply-templates select="persons"/> </people> </xsl:template> <!-- 匹配每个persons节点,输出自定义的person结构 --> <xsl:template match="persons"> <person> <id> <xsl:value-of select="person_id"/> </id> <!-- 预留位置,后续添加字符串拆分逻辑 --> <split_strings> <xsl:apply-templates select="oneofs/oneof"/> </split_strings> </person> </xsl:template> </xsl:stylesheet>
二、拆分XML中的字符串
如果你的XSLT处理器支持XSLT 2.0及以上(比如Saxon),可以直接用内置的tokenize()函数,它能按指定分隔符拆分字符串。咱们把上面的XSLT补充完整,实现把<oneof>里的长字符串按空格拆分:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 匹配根节点,输出新的根结构 --> <xsl:template match="/root"> <people> <!-- 遍历所有persons节点 --> <xsl:apply-templates select="persons"/> </people> </xsl:template> <!-- 匹配每个persons节点,输出自定义的person结构 --> <xsl:template match="persons"> <person> <id> <xsl:value-of select="person_id"/> </id> <split_strings> <xsl:apply-templates select="oneofs/oneof"/> </split_strings> </person> </xsl:template> <!-- 匹配oneof节点,拆分字符串 --> <xsl:template match="oneof"> <!-- 用tokenize按空格拆分,遍历每个拆分后的片段 --> <xsl:for-each select="tokenize(., ' ')"> <word> <xsl:value-of select="."/> </word> </xsl:for-each> </xsl:template> </xsl:stylesheet>
转换后的结果
用上面的XSLT处理示例XML,会得到这样的输出:
<?xml version="1.0" encoding="UTF-8"?> <people> <person> <id>_:genid1</id> <split_strings> <word>This</word> <word>is</word> <word>a</word> <word>very</word> <word>long</word> <word>string</word> </split_strings> </person> <person> <id>_:genid2</id> <split_strings> <word>Another</word> <word>example</word> <word>string</word> <word>here</word> </split_strings> </person> </people>
如果只能用XSLT 1.0怎么办?
XSLT 1.0没有内置的tokenize()函数,这时候需要自定义一个递归模板来拆分字符串。比如可以加这样的模板:
<!-- XSLT 1.0 自定义拆分模板 --> <xsl:template name="split-string"> <xsl:param name="input-string"/> <xsl:param name="delimiter" select="' '"/> <xsl:choose> <xsl:when test="contains($input-string, $delimiter)"> <word> <xsl:value-of select="substring-before($input-string, $delimiter)"/> </word> <!-- 递归处理剩余的字符串 --> <xsl:call-template name="split-string"> <xsl:with-param name="input-string" select="substring-after($input-string, $delimiter)"/> <xsl:with-param name="delimiter" select="$delimiter"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <word> <xsl:value-of select="$input-string"/> </word> </xsl:otherwise> </xsl:choose> </xsl:template>
然后在匹配oneof的模板里调用它:
<xsl:template match="oneof"> <xsl:call-template name="split-string"> <xsl:with-param name="input-string" select="."/> </xsl:call-template> </xsl:template>
这样就能在XSLT 1.0环境下实现同样的字符串拆分效果啦。
内容的提问来源于stack exchange,提问作者user9566024
相关产品推荐
相关产品推荐

