是将文本转换为XML结构的XSLT好办法? [英] Is xslt good approach to convert text to xml structure?

查看:232
本文介绍了是将文本转换为XML结构的XSLT好办法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到一个更好的解决方案转换为纯文本(但每个字段的预定义长度)到XML。
例如输入文字可以
TESTUSER纽约10018,第11个字符显示的用户名,接下来的12个字符表示城市,未来5个字符表示邮政编码。
所以我需要形成从上面的字符串与预定义的字段长度一个XML。



我想方法2




  1. 定义一个商业实体,并通过对输入文本串功能填补了实体属性,然后序列化实体XML


  2. 预定义的XML结构,使用XSLT导航到每个节点,并使用输入的文本字符串函数由
    填充值。



解决方案

的语句:(XSLT)不适合从结构化文本转化XML。及本声明XSLT 必须 对XML作为输入文件 **都是错误




我想方法2




  1. 定义一个商业实体,并通过对输入文本串功能填补了实体属性,然后序列化实体
    XML


  2. 预定义的XML结构,使用XSLT导航到每一个节点,并通过对输入字符串函数填充值文本。





其实,方法2是很容易实现使用XSLT



我。 XSLT 1.0



 <的xsl:样式版本=1.0
的xmlns:XSL = http://www.w3.org/1999/XSL/Transform\">
< XSL:输出中省略的XML声明=YES缩进=YES/>

<的xsl:模板匹配=/ * /文本()NAME =processLines>
< XSL:PARAM NAME =pText选择= />中。

<的xsl:if测试=包含($ pText,'和; #xA;')>
< XSL:变量名=U电源选择=
子 - 前($ pText,'和; #xA;')/>

<使用者>
<名称>
<的xsl:value-of的(')'','子串的前($ VLINE,_)翻译选择=
/>
< /名称>
<城市>
<的xsl:value-of的')',选择=
翻译(子 - 前(子-后($ VLINE,'')
'_',
''

/>
< /城市>
<邮编>
<的xsl:value-of的,',)',选择=
翻译(子-后(子-后($ U电源'')
'_',
''

/>
< /邮政编码>
< /使用者名称>

< XSL:呼叫模板名称=processLines>
< XSL:用-PARAM NAME =pText选择=
子-后($ pText,'和; #xA;')/>
< / XSL:调用模板>
< / XSL:如果>
< / XSL:模板>
< / XSL:样式>



当上了特殊格式的文本应用这种转变(包裹内的要进行单个顶级元素以及形成 - 我们将在XSLT 2.0看到这样的包装是没有必要的):

 < T> TESTUSER new_york 10018 
用户A西雅图98000
用户b贝尔维尤98004
用户b雷德蒙98052
< / T>



通缉的结果是产生



 <使用者> 
<名称>&TESTUSER LT; /名称>
<城市>纽约< /城市>
<邮编> 10018< /邮政编码>
< /使用者名称>
<使用者>
<名称>&用户A LT; /名称>
<城市>西雅图< /城市>
<邮编> 98000< /邮政编码>
< /使用者名称>
<使用者>
<名称>&用户B LT; /名称>
<城市>&贝尔维尤LT; /城市>
<邮编> 98004< /邮政编码>
< /使用者名称>
<使用者>
<名称>&用户B LT; /名称>
<城市>微软< /城市>
<邮编> 98052< /邮政编码>
< /使用者名称>

备注




  1. 这仅仅是演示如何完成任务的演示。这就是为什么我不处理固定宽度字段(控制而会更容易),但是空间的分隔值。


  2. 输入包含在任何值的任何空间在输入为下划线(或我们选择的任何角色,我们知道将永远不会有任何价值的一部分。在输出时,任何下划线转换为一个真正的空间。




II XSLT 2.0解决方案

  <的xsl:样式版本=2.0
的xmlns:XSL =htt​​p://www.w3.org/1999/XSL/Transform>
< XSL:输出中省略,XML的声明=YES缩进=YES/>

< XSL:变量名=vText选择=
未解析文本(文件:/// C: /temp/delete/delete.txt')\"/>

< XSL:变量名=vLines选择=
标记化($ vText,'和; #xD; ?&安培; #xA;')[正常化空间()]/>

<的xsl:模板匹配=/>
<的xsl:for-每个选择=$ vLines>
< XSL:变量名=vFields选择=
标记化[正常化空间()]('')/>
<使用者>
<名称>
< XSL:依次选择=翻译($ vFields [1],'_','')/>
< /名称>
<城市>
< XSL:依次选择=翻译($ vFields [2],'_','')/>
< /城市>
<邮编>
< XSL:依次选择=翻译($ vFields [3],'_','')/>
< /邮政编码>
< /使用者名称>
< /的xsl:for-每个>
< / XSL:模板>
< / XSL:样式>



当任何XML文档应用这种转变(未使用,实际上没有必要,因为在XSLT 2.0没有必要有一个源XML文档)和如果文件 C:\temp\delete\delete.txt

  TESTUSER new_york 10018 
用户A西雅图98000
用户b贝尔维尤98004
用户b雷德蒙98052

再次通缉,正确的结果是产生

 <使用者> 
<名称>&TESTUSER LT; /名称>
<城市>纽约< /城市>
<邮编> 10018< /邮政编码>
< /使用者名称>
<使用者>
<名称>&用户A LT; /名称>
<城市>西雅图< /城市>
<邮编> 98000< /邮政编码>
< /使用者名称>
<使用者>
<名称>&用户B LT; /名称>
<城市>&贝尔维尤LT; /城市>
<邮编> 98004< /邮政编码>
< /使用者名称>
<使用者>
<名称>&用户B LT; /名称>
<城市>微软< /城市>
<邮编> 98052< /邮政编码>
< /使用者名称>

备注




  1. 标准XSLT 2.0功能的使用 未解析文本()


  2. 标准的XPath 2.0函数的使用 标记化()




最后说明



最复杂的文本处理已经完全在XSLT工业的方式已经完成。 的FXSL库 包含一个通用的 LR(1)语法分析器 和< STRONG> 调整YACC产生XML格式的表格 是输入该通用运行时间LR(1)语法分析器



使用这个工具,我成功的内置解析器 对于这样复杂的语言为JSON和XPath 2.0。


I am trying to find a better solution to convert a plain text (but with predefined lengths for each field) to xml. For example the input text can be "Testuser new york 10018", the first 11 characters indicates user name, next 12 character indicates city and next 5 characters indicates zip code. So I need to form a xml from the above string with predefined field lengths.

I am thinking 2 approaches

  1. Define a business entity and fill the entity properties by using substring functions on the input text and then serialize the entity to xml

  2. Predefine the xml structure, use xslt to navigate to each node and fill the values by using substring functions on the input text.

解决方案

The statements that: (XSLT) "isn't suitable for transforming from structured text to XML. " and the statement "XSLTmusthave XML as the input document" **are both wrong.

I am thinking 2 approaches

  1. Define a business entity and fill the entity properties by using substring functions on the input text and then serialize the entity to xml

  2. Predefine the xml structure, use xslt to navigate to each node and fill the values by using substring functions on the input text.

In fact, Approach 2 is quite easy to accomplish with XSLT:

I. XSLT 1.0:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*/text()" name="processLines">
  <xsl:param name="pText" select="."/>

  <xsl:if test="contains($pText, '&#xA;')">
    <xsl:variable name="vLine" select=
     "substring-before($pText, '&#xA;')"/>

     <user>
       <name>
         <xsl:value-of select=
         "translate(substring-before($vLine, ' '),'_',' ')"/>
       </name>
       <city>
         <xsl:value-of select=
         "translate(substring-before(substring-after($vLine, ' '),' '),
                    '_',
                    ' '
                    )
         "/>
       </city>
       <zipCode>
         <xsl:value-of select=
         "translate(substring-after(substring-after($vLine, ' '),' '),
                    '_',
                    ' '
                    )
         "/>
       </zipCode>
     </user>

     <xsl:call-template name="processLines">
      <xsl:with-param name="pText" select=
      "substring-after($pText, '&#xA;')"/>
     </xsl:call-template>
  </xsl:if>
  </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the specially formatted text (wrapped within a single top element to be made well-formed -- as we'll see in XSLT 2.0 such wrapping isn't necessary):

<t>Testuser new_york 10018
usera seattle 98000
userb bellevue 98004
userb redmond 98052
</t>

the wanted result is produced:

<user>
   <name>Testuser</name>
   <city>new york</city>
   <zipCode>10018</zipCode>
</user>
<user>
   <name>usera</name>
   <city>seattle</city>
   <zipCode>98000</zipCode>
</user>
<user>
   <name>userb</name>
   <city>bellevue</city>
   <zipCode>98004</zipCode>
</user>
<user>
   <name>userb</name>
   <city>redmond</city>
   <zipCode>98052</zipCode>
</user>

Notes:

  1. This is just a demo that demonstrates how to accomplish the task. This is why I am not processing fixed-width fields (whil would be even easier), but space separated values.

  2. Any space contained in any value is entered in the input as underscore (or any character of our choosing, that we know will never be part of any value. On output, any underscore is translated to a real space.

II. XSLT 2.0 solution:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vText" select=
  "unparsed-text('file:///c:/temp/delete/delete.txt')"/>

 <xsl:variable name="vLines" select=
  "tokenize($vText, '&#xD;?&#xA;')[normalize-space()]"/>

 <xsl:template match="/">
  <xsl:for-each select="$vLines">
    <xsl:variable name="vFields" select=
    "tokenize(., ' ')[normalize-space()]"/>
   <user>
     <name>
       <xsl:sequence select="translate($vFields[1], '_',' ')"/>
     </name>
     <city>
       <xsl:sequence select="translate($vFields[2], '_',' ')"/>
     </city>
     <zipCode>
       <xsl:sequence select="translate($vFields[3], '_',' ')"/>
     </zipCode>
   </user>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on any XML document (not used and actually not needed, as in XSLT 2.0 it isn't necessary to have a source XML document), and if the file C:\temp\delete\delete.txt is:

Testuser new_york 10018
usera seattle 98000
userb bellevue 98004
userb redmond 98052

again the wanted, correct result is produced:

<user>
   <name>Testuser</name>
   <city>new york</city>
   <zipCode>10018</zipCode>
</user>
<user>
   <name>usera</name>
   <city>seattle</city>
   <zipCode>98000</zipCode>
</user>
<user>
   <name>userb</name>
   <city>bellevue</city>
   <zipCode>98004</zipCode>
</user>
<user>
   <name>userb</name>
   <city>redmond</city>
   <zipCode>98052</zipCode>
</user>

Notes:

  1. Use of the standard XSLT 2.0 function unparsed-text().

  2. Use of the standard XPath 2.0 function tokenize().

Final note:

Most complex text processing has been done in an industrial way entirely in XSLT. The FXSL library contains a generic LR(1) parser and a tweaked YACC that produces XML-formatted tables that are the input to this generic run-time LR(1) parser.

Using this tool I successfully built parsers for such complex languages as JSON and XPath 2.0.

这篇关于是将文本转换为XML结构的XSLT好办法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆