如建议的那样。我打破了这个问题here 分成几部分。
我的输入xml表示字符串中存在字段。输入xml最多可包含64个字段元素。输入xml字段元素始终按升序出现。 我的输入xml
<Root>
<element>field2</element>
<element>field3</element>
<element>field21</element>
</Root>
字符串被定义为xslt中的变量。
我的变量
<xsl:variable name="inputstring" select="'013112316145ABC0812345678'"/>
输入xml表示字段2,3和21是字符串中唯一要根据映射xml提取的字段
这是映射xml
<Root>
<field no="2" charlength="2">variable</field>
<field no="3" total="4">fixed</field>
<field no="21" charlength="2">
<subfield no="1" total="3">fixed</subfield>
<subfield no="2" charlength="2" idcode="ABC">variable</subfield>
</field>
<field no="63" charlength="2">
<format1>
<subfield no="1" total="3">fixed</subfield>
</format1>
<format2>
<subfield no="1" total="3">fixed</subfield>
<subfield no="2" total="7">fixed</subfield>
</format2>
<format3>
<subfield no="1" total="3">fixed</subfield>
<subfield no="2" total="7">fixed</subfield>
<subfield no="3" total="6">fixed</subfield>
</format3>
</field>
</Root>
映射xml告诉以下
我想要的输出xml
<Root>
<field2>3</field2>
<!--value is 3 as the charlength is 2(which is 01)-->
<field3>1123</field3>
<!--field3 value is 1123 as it is fixed, total length of 4-->
<field21>
<subfield1>145</subfield1>
<!--subfield1 should be 145 as it is fixed length of total 3 chars-->
<subfield2>12345678</subfield2>
<!--sufield2 starts with 'ABC', has length 08 chars-->
</field21>
</Root>
肖恩编辑。
这是输入和输出之间映射的细分。
这是我们的字符串变量$ inputstring
的图片'013112316145ABC0812345678'
根据字段定义分为3个字段......
013 - 1123 - 16145ABC0812345678
| | v
v v field 21
field2 field3
让我们分解字段2:
01 3
| v
| payload for field 2. This is output
v
Contains the length(1) of the payload, which in this case is '01' = 1
This length of this 'header' is given by mapping Root/field[@no="2"]/@charlength
The "2" in this expression comes from the input document node at Root/element .
让分解字段21:
16 145 ABC0812345678
| | v
| | subfield 2
| \ subfield 1
\
v
Header for field 2. Says that the total field 2 length (header + subfield 1 +
subfield 2 consists of 16 characters. The length for this header was derived from
the mapping node at Root/field[@no="21"]/@charlength .
最后一个例子:字段21 /子字段2的细分。这是子字段2的图片
ABC 08 12345678
| | |
| | v
| | This is the payload. It is output as the text node child of output
| | subfield 2
| v
v Length of the following payload
Signature. The length and value is equal to the mapping node
Root/field[@no="21"]/subfield[@no="2"]/@idcode
答案 0 :(得分:2)
嗯.....我说我不会这样做,但无论如何我都是这样做的。
这个XSLT 1.0样式表...
<xsl:stylesheet version="1.0"
exclude-result-prefixes="xsl so msxsl"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:so="http://stackoverflow.com/questions/12035679"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:variable name="inputstring" select="'013112316145ABC0812345678'" />
<xsl:variable name="map">
<so:mapping>
<field no="2" charlength="2">variable</field>
<field no="3" total="4">fixed</field>
<field no="21" charlength="2">
<subfield no="1" total="3">fixed</subfield>
<subfield no="2" charlength="2" idcode="ABC">variable</subfield>
</field>
</so:mapping>
</xsl:variable>
<xsl:template match="/*">
<xsl:copy>
<xsl:call-template name="process-fields">
<xsl:with-param name="element-stack" select="element" />
<xsl:with-param name="code" select="$inputstring" />
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="process-fields">
<xsl:param name="element-stack" />
<xsl:param name="code" />
<xsl:if test="($code != '') and $element-stack">
<xsl:variable name="field-no" select="
substring-after($element-stack[1],'field')" />
<xsl:variable name="field-parse-request">
<so:field-parse-request code="{$code}">
<xsl:copy-of select="msxsl:node-set($map)/so:mapping/
field [@no=$field-no]" />
</so:field-parse-request>
</xsl:variable>
<xsl:variable name="field-parse-result">
<xsl:apply-templates
select="msxsl:node-set($field-parse-request)/*"
mode="field-parse" />
</xsl:variable>
<xsl:apply-templates
select="msxsl:node-set($field-parse-result)/so:output/*"
mode="remove-namespaces" />
<xsl:call-template name="process-fields">
<xsl:with-param name="element-stack"
select="$element-stack[position() > 1]" />
<xsl:with-param name="code"
select="msxsl:node-set($field-parse-result)/
so:output[1]/@code" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="so:field-parse-request[field[subfield]]"
mode="field-parse">
<so:output>
<xsl:variable name="header"
select="substring(@code,1,field/@charlength)" />
<xsl:attribute name="code">
<xsl:value-of
select="substring(@code,1+field/@charlength+$header)" />
</xsl:attribute>
<xsl:element name="field{field/@no}">
<xsl:call-template name="process-subfields">
<xsl:with-param name="subfield-stack" select="field/subfield" />
<xsl:with-param
name="code"
select="substring(@code,1+field/@charlength,$header)" />
</xsl:call-template>
</xsl:element>
</so:output>
</xsl:template>
<xsl:template match="so:field-parse-request[field[.='variable']]"
mode="field-parse">
<so:output>
<xsl:variable name="header"
select="substring(@code,1,field/@charlength)" />
<xsl:attribute name="code">
<xsl:value-of select="substring(@code,1+field/@charlength+$header)" />
</xsl:attribute>
<xsl:element name="field{field/@no}">
<xsl:value-of select="substring(@code,1+field/@charlength,$header)" />
</xsl:element>
</so:output>
</xsl:template>
<xsl:template match="so:field-parse-request[subfield[.='variable']]"
mode="field-parse">
<so:output>
<xsl:variable name="header"
select="substring( @code,
1 + string-length( subfield/@idcode),
subfield/@charlength)" />
<xsl:attribute name="code">
<xsl:value-of select="substring(
@code,
1 + string-length( subfield/@idcode) +
subfield/@charlength + $header)" />
</xsl:attribute>
<xsl:element name="subfield{subfield/@no}">
<xsl:value-of select="
substring( @code,
1 + string-length( subfield/@idcode) +
subfield/@charlength, $header)" />
</xsl:element>
</so:output>
</xsl:template>
<xsl:template match="so:field-parse-request[ field[.='fixed']] | so:field-parse-request[subfield[.='fixed']]" mode="field-parse">
<so:output>
<xsl:attribute name="code">
<xsl:value-of select="substring(@code, (field/@total | subfield/@total) + 1)" />
</xsl:attribute>
<xsl:element name="{concat( name(field|subfield) ,field/@no | subfield/@no)}">
<xsl:value-of select="substring(@code,1,field/@total | subfield/@total)" />
</xsl:element>
</so:output>
</xsl:template>
<xsl:template name="process-subfields">
<xsl:param name="subfield-stack" />
<xsl:param name="code" />
<xsl:if test="($code != '') and $subfield-stack">
<xsl:variable name="active-subfield-index">
<xsl:choose>
<xsl:when test="not( $subfield-stack[1]/@idcode)">1</xsl:when>
<xsl:otherwise>
<xsl:value-of select="
count($subfield-stack
[starts-with($code,@idcode)]/preceding-sibling::*)+1" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="field-parse-request">
<so:field-parse-request code="{$code}">
<xsl:copy-of select="$subfield-stack[$active-subfield-index]" />
</so:field-parse-request>
</xsl:variable>
<xsl:variable name="field-parse-result">
<xsl:apply-templates
select="msxsl:node-set($field-parse-request)/*"
mode="field-parse" />
</xsl:variable>
<xsl:apply-templates
select="msxsl:node-set($field-parse-result)/so:output/*"
mode="remove-namespaces" />
<xsl:call-template name="process-subfields">
<xsl:with-param name="subfield-stack"
select="$subfield-stack[position() != $active-subfield-index]" />
<xsl:with-param name="code"
select="msxsl:node-set($field-parse-result)/
so:output[1]/@code" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="*" mode="remove-namespaces">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="@*|node()" mode="remove-namespaces" />
</xsl:element>
</xsl:template>
<xsl:template match="@*|text()" mode="remove-namespaces">
<xsl:copy />
</xsl:template>
</xsl:stylesheet>
...将采用此输入文档......
<Root>
<element>field2</element>
<element>field3</element>
<element>field21</element>
</Root>
...并根据规则5规定的所有规则对其进行转换,并生成此输出...
<Root>
<field2>3</field2>
<field3>1123</field3>
<field21>
<subfield1>145</subfield1>
<subfield2>12345678</subfield2>
</field21>
</Root>