我想了解如何进行String查找以及如何分别解析逗号分隔的String。但是我想知道是否有一种有效的方法来满足这两个要求。这是我的源XML:
<?xml version="1.0" ?>
<MATRIX>
<DATA_RECORD>
<COMPONENT1>1, 2</COMPONENT1>
<COMPONENT2>6, 7, 8, 9</COMPONENT2>
</DATA_RECORD>
</MATRIX>
我希望通过解析逗号分隔的String并使用每个令牌进行查找来生成以下XML:
<?xml version="1.0" encoding="UTF-8"?>
<MATRIX>
<DATA_RECORD>
<COMPONENT1>A, B</COMPONENT1>
<COMPONENT2>F, G, H, I</COMPONENT2>
</DATA_RECORD>
</MATRIX>
这是我的查找XML(COMPONENT_LOOKUPLIST.xml):
<?xml version="1.0" ?>
<MAIN>
<DATA_RECORD>
<COMPONENT_ID>1</COMPONENT_ID>
<COMPONENT_NAME>A</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>2</COMPONENT_ID>
<COMPONENT_NAME>B</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>3</COMPONENT_ID>
<COMPONENT_NAME>C</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>4</COMPONENT_ID>
<COMPONENT_NAME>D</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>5</COMPONENT_ID>
<COMPONENT_NAME>E</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>6</COMPONENT_ID>
<COMPONENT_NAME>F</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>7</COMPONENT_ID>
<COMPONENT_NAME>G</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>8</COMPONENT_ID>
<COMPONENT_NAME>H</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>9</COMPONENT_ID>
<COMPONENT_NAME>I</COMPONENT_NAME>
</DATA_RECORD>
</MAIN>
我是XSLT的初学者。一些XSLT专家可以分享一些想法或提供示例代码吗?我从Jeni的网站上获得了令牌代码:
<xsl:template name="tokenize">
<xsl:param name="string" />
<xsl:param name="delimiter" select="','" />
<xsl:choose>
<xsl:when test="$delimiter and contains($string, $delimiter)">
<token>
<xsl:value-of select="substring-before($string, $delimiter)" />
</token>
<xsl:call-template name="tokenize">
<xsl:with-param name="string"
select="substring-after($string, $delimiter)" />
<xsl:with-param name="delimiter" select="$delimiter" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<token><xsl:value-of select="$string" /></token>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:call-template name="tokenize">
<xsl:with-param name="string" select="/MATRIX/DATA_RECORD/COMPONENT1"></xsl:with-param>
</xsl:call-template>
<xsl:call-template name="tokenize">
<xsl:with-param name="string" select="/MATRIX/DATA_RECORD/COMPONENT2"></xsl:with-param>
</xsl:call-template>
并写了一个查找:
<xsl:variable name="lookup" select="document('COMPONENT_LOOKUPLIST.xml')/MAIN/DATA_RECORD"/>
<xsl:for-each select="//DATA_RECORD">
<token>
<xsl:for-each select="*">
<xsl:value-of select="$lookup[COMPONENT_ID = current()]/COMPONENT_NAME"/>
</xsl:for-each>
</token>
</xsl:for-each>
但将这两者结合起来似乎很有挑战性。
谢谢。
答案 0 :(得分:0)
您是否考虑使用像Saxon 9或AltovaXML或XmlPrime这样的XSLT 2.0处理器?在这种情况下,你可以很容易地做到。
<xsl:key name="by-id" match="DATA_RECORD" use="COMPONENT_ID"/>
<xsl:param name="lk-doc-url" select="'COMPONENT_LOOKUPLIST.xml'"/>
<xsl:variable name="lk-doc" select="document($lk-doc-url)"/>
<xsl:template match="*[starts-with(local-name(), 'COMPONENT')]">
<xsl:copy>
<xsl:value-of select="for $id in tokenize(., ', ') return key('by-id', $id, $lk-doc)/COMPONENT_NAME"
separator=", "/>
</xsl:copy>
</xsl:template>
[编辑] 这是一个完整且经过测试的样本:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:key name="by-id" match="DATA_RECORD" use="COMPONENT_ID"/>
<xsl:param name="lk-doc-url" select="'test2013013103.xml'"/>
<xsl:variable name="lk-doc" select="document($lk-doc-url)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(local-name(), 'COMPONENT')]">
<xsl:copy>
<xsl:value-of select="for $id in tokenize(., ', ') return key('by-id', $id, $lk-doc)/COMPONENT_NAME"
separator=", "/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当我将Saxon 9.4应用于输入
时<?xml version="1.0" ?>
<MATRIX>
<DATA_RECORD>
<COMPONENT1>1, 2</COMPONENT1>
<COMPONENT2>6, 7, 8, 9</COMPONENT2>
</DATA_RECORD>
</MATRIX>
查找文件test2013013103.xml
的是
<?xml version="1.0" ?>
<MAIN>
<DATA_RECORD>
<COMPONENT_ID>1</COMPONENT_ID>
<COMPONENT_NAME>A</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>2</COMPONENT_ID>
<COMPONENT_NAME>B</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>3</COMPONENT_ID>
<COMPONENT_NAME>C</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>4</COMPONENT_ID>
<COMPONENT_NAME>D</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>5</COMPONENT_ID>
<COMPONENT_NAME>E</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>6</COMPONENT_ID>
<COMPONENT_NAME>F</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>7</COMPONENT_ID>
<COMPONENT_NAME>G</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>8</COMPONENT_ID>
<COMPONENT_NAME>H</COMPONENT_NAME>
</DATA_RECORD>
<DATA_RECORD>
<COMPONENT_ID>9</COMPONENT_ID>
<COMPONENT_NAME>I</COMPONENT_NAME>
</DATA_RECORD>
</MAIN>
输出
<?xml version="1.0" encoding="UTF-8"?><MATRIX>
<DATA_RECORD>
<COMPONENT1>A, B</COMPONENT1>
<COMPONENT2>F, G, H, I</COMPONENT2>
</DATA_RECORD>
</MATRIX>
所以我的建议有效,我不确定你的情况有什么不同,你没有得到任何内容。
答案 1 :(得分:0)
如果您遇到XSLT1.0,一个解决方案可能是修改 tokenize 模板进行查找,而不是吐出令牌元素(如果你保留了标记元素,你必须进行两遍变换,根据你的查找将它们转换回字符串。
所以,而不是在 tokenize 模板中执行此操作
<token>
<xsl:value-of select="substring-before($string, $delimiter)" />
</token>
这样做,而不是
<xsl:value-of select="$lookup[COMPONENT_ID=normalize-space(substring-before($string, $delimiter))]/COMPONENT_NAME"/>
<xsl:value-of select="$delimiter"/>
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" method="html"/>
<xsl:variable name="lookup" select="document('C:\COMPONENT_LOOKUPLIST.xml')/MAIN/DATA_RECORD"/>
<xsl:template match="DATA_RECORD/*">
<xsl:copy>
<xsl:call-template name="tokenize">
<xsl:with-param name="string" select="."/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="string"/>
<xsl:param name="delimiter" select="','"/>
<xsl:choose>
<xsl:when test="$delimiter and contains($string, $delimiter)">
<xsl:value-of select="$lookup[COMPONENT_ID=normalize-space(substring-before($string, $delimiter))]/COMPONENT_NAME"/>
<xsl:value-of select="$delimiter"/>
<xsl:call-template name="tokenize">
<xsl:with-param name="string" select="substring-after($string, $delimiter)"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$lookup[COMPONENT_ID=normalize-space($string)]/COMPONENT_NAME"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
应用于XML时,输出以下内容
<MATRIX>
<DATA_RECORD>
<COMPONENT1>A,B</COMPONENT1>
<COMPONENT2>F,G,H,I</COMPONENT2>
</DATA_RECORD>
</MATRIX>
注意,这确实会删除空格,但希望这不是问题...
编辑:如果你想保留空格,你可以这样做:
<xsl:variable name="current" select="substring-before($string, $delimiter)" />
<xsl:value-of select="substring-before($current, normalize-space($current))" />
<xsl:value-of select="$lookup[COMPONENT_ID=normalize-space($)]/COMPONENT_NAME"/>
<xsl:value-of select="substring-after($current, normalize-space($current))" />