提取分隔数据
Extract delimited data
我有以下格式的输入分隔数据
A;B;C;D;E;F;G;H;I;J;K
输出应该是这样的
<1>A</1>
<2>B</2>
<3>C</3>
<4>D</4>
<5>E</5>
<6>F</6>
<7>G</7>
<8>H</8>
<9>I</9>
<10>J</10>
<11>K</11>
上面提到的是这个分隔字符串的最大长度。已经编写了一个 xslt 以便能够分隔定界字符串并使用多个子字符串获得所需的输出,如下所述并能够获得输出
<xsl:value-of
select="substring-before(substring-after(substring-after(substring-after(string,';'),';'),';'),';')"/>
问题:提供商并非始终以上述 A;B;C;D;E;F;G;H;I;J;K
格式发送数据。
当有空值时,我们假设它看起来像 A;B;C;D;;;;;;;
。
但是在这种情况下,我们收到的是 A;B;C;D
并且后面没有空分隔符。
假设我们的字符串是固定长度的,我们的提取逻辑使用上面的前后工作。如果不遵守长度,我们将无法提取数据。
有人可以帮助解决与接收到的长度无关的逻辑,即第一个定界符之前的数据始终为 <1> 并且 1 和 2 之间的定界符为 <2> 等等。
您可以使用递归模板来处理标记。您可以传入总数量,这样即使不是所有标记都存在,仍会创建一个元素。
示例...
XML 输入
<doc>
<string>A;B;C;D;E;F;G;H;I;J;K</string>
<string>A;B;C;D</string>
<string>A;B;C;;;;G;H;I;J;K</string>
<string/>
</doc>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="string">
<xsl:copy>
<xsl:call-template name="process_string"/>
</xsl:copy>
</xsl:template>
<xsl:template name="process_string">
<xsl:param name="str" select="."/>
<xsl:param name="qty" select="11"/>
<xsl:param name="item_cnt" select="1"/>
<xsl:variable name="remaining_qty" select="$qty - 1"/>
<xsl:variable name="item_value" select="normalize-space(
substring-before(concat($str, ';'), ';'))"/>
<xsl:element name="item{$item_cnt}">
<xsl:value-of select="$item_value"/>
</xsl:element>
<xsl:if test="substring-after($str,';') or $remaining_qty > 0">
<xsl:call-template name="process_string">
<xsl:with-param name="str" select="substring-after($str,';')"/>
<xsl:with-param name="qty" select="$remaining_qty"/>
<xsl:with-param name="item_cnt" select="$item_cnt + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
输出
<doc>
<string>
<item1>A</item1>
<item2>B</item2>
<item3>C</item3>
<item4>D</item4>
<item5>E</item5>
<item6>F</item6>
<item7>G</item7>
<item8>H</item8>
<item9>I</item9>
<item10>J</item10>
<item11>K</item11>
</string>
<string>
<item1>A</item1>
<item2>B</item2>
<item3>C</item3>
<item4>D</item4>
<item5/>
<item6/>
<item7/>
<item8/>
<item9/>
<item10/>
<item11/>
</string>
<string>
<item1>A</item1>
<item2>B</item2>
<item3>C</item3>
<item4/>
<item5/>
<item6/>
<item7>G</item7>
<item8>H</item8>
<item9>I</item9>
<item10>J</item10>
<item11>K</item11>
</string>
<string>
<item1/>
<item2/>
<item3/>
<item4/>
<item5/>
<item6/>
<item7/>
<item8/>
<item9/>
<item10/>
<item11/>
</string>
</doc>
我有以下格式的输入分隔数据
A;B;C;D;E;F;G;H;I;J;K
输出应该是这样的
<1>A</1>
<2>B</2>
<3>C</3>
<4>D</4>
<5>E</5>
<6>F</6>
<7>G</7>
<8>H</8>
<9>I</9>
<10>J</10>
<11>K</11>
上面提到的是这个分隔字符串的最大长度。已经编写了一个 xslt 以便能够分隔定界字符串并使用多个子字符串获得所需的输出,如下所述并能够获得输出
<xsl:value-of
select="substring-before(substring-after(substring-after(substring-after(string,';'),';'),';'),';')"/>
问题:提供商并非始终以上述 A;B;C;D;E;F;G;H;I;J;K
格式发送数据。
当有空值时,我们假设它看起来像 A;B;C;D;;;;;;;
。
但是在这种情况下,我们收到的是 A;B;C;D
并且后面没有空分隔符。
假设我们的字符串是固定长度的,我们的提取逻辑使用上面的前后工作。如果不遵守长度,我们将无法提取数据。
有人可以帮助解决与接收到的长度无关的逻辑,即第一个定界符之前的数据始终为 <1> 并且 1 和 2 之间的定界符为 <2> 等等。
您可以使用递归模板来处理标记。您可以传入总数量,这样即使不是所有标记都存在,仍会创建一个元素。
示例...
XML 输入
<doc>
<string>A;B;C;D;E;F;G;H;I;J;K</string>
<string>A;B;C;D</string>
<string>A;B;C;;;;G;H;I;J;K</string>
<string/>
</doc>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="string">
<xsl:copy>
<xsl:call-template name="process_string"/>
</xsl:copy>
</xsl:template>
<xsl:template name="process_string">
<xsl:param name="str" select="."/>
<xsl:param name="qty" select="11"/>
<xsl:param name="item_cnt" select="1"/>
<xsl:variable name="remaining_qty" select="$qty - 1"/>
<xsl:variable name="item_value" select="normalize-space(
substring-before(concat($str, ';'), ';'))"/>
<xsl:element name="item{$item_cnt}">
<xsl:value-of select="$item_value"/>
</xsl:element>
<xsl:if test="substring-after($str,';') or $remaining_qty > 0">
<xsl:call-template name="process_string">
<xsl:with-param name="str" select="substring-after($str,';')"/>
<xsl:with-param name="qty" select="$remaining_qty"/>
<xsl:with-param name="item_cnt" select="$item_cnt + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
输出
<doc>
<string>
<item1>A</item1>
<item2>B</item2>
<item3>C</item3>
<item4>D</item4>
<item5>E</item5>
<item6>F</item6>
<item7>G</item7>
<item8>H</item8>
<item9>I</item9>
<item10>J</item10>
<item11>K</item11>
</string>
<string>
<item1>A</item1>
<item2>B</item2>
<item3>C</item3>
<item4>D</item4>
<item5/>
<item6/>
<item7/>
<item8/>
<item9/>
<item10/>
<item11/>
</string>
<string>
<item1>A</item1>
<item2>B</item2>
<item3>C</item3>
<item4/>
<item5/>
<item6/>
<item7>G</item7>
<item8>H</item8>
<item9>I</item9>
<item10>J</item10>
<item11>K</item11>
</string>
<string>
<item1/>
<item2/>
<item3/>
<item4/>
<item5/>
<item6/>
<item7/>
<item8/>
<item9/>
<item10/>
<item11/>
</string>
</doc>