使用XSLT 2.0在文本文件中读取时如何添加父元素?

时间:2014-11-25 19:23:08

标签: xml xslt xslt-2.0

我必须使用XSLT 2.0读取文本文件并输出XML。输入文本文件如:

Start:000,A:123,B:234,C:33,End:99,Start:03,A:123d,B:234s,End:992,Start:a00,B:234,C:33,End:99

所需的XML输出如下:

<File>
<Rec>
    <Start>000</Start>
    <A>123</A>
    <B>234</B>
    <C>33</C>
    <End>99</End>
</Rec>
<Rec>
    <Start>03</Start>
    <A>123d</A>
    <B>234s</B>
    <End>992</End>
</Rec>
<Rec>
    <Start>a00</Start>
    <B>234</B>
    <C>33</C>
    <End>99</End>
</Rec>

我很难将元素从“开始”分组到“结束”并向其添加父元素“Rec”。有什么建议吗?非常感谢!

2 个答案:

答案 0 :(得分:3)

您可以使用unparsed-text()tokenize()来创建您正在寻找的输出。如果文本文件可能包含多行,您也可以使用xsl:analyze-string

示例...

文字输入(so.txt)

Start:000,A:123,B:234,C:33,End:99,Start:03,A:123d,B:234s,End:992,Start:a00,B:234,C:33,End:99

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="input-encoding" as="xs:string" select="'iso-8859-1'"/>
    <xsl:param name="input-uri" as="xs:string" select="'so.txt'"/>

    <xsl:template match="/">
        <xsl:variable name="input" select="unparsed-text($input-uri, $input-encoding)"/>
        <File>
            <xsl:analyze-string select="$input" regex="\r\n?|\n">
                <xsl:non-matching-substring>
                    <xsl:for-each select="tokenize(.,'Start')[string()]">
                        <Rec>
                            <xsl:for-each select="tokenize(.,',')[string()]">
                                <xsl:variable name="vals" select="tokenize(.,':')"/>
                                <xsl:element name="{if (position()=1) then 'Start' else $vals[1]}">
                                    <xsl:value-of select="$vals[2]"/>
                                </xsl:element>
                            </xsl:for-each>                            
                        </Rec>
                    </xsl:for-each>
                </xsl:non-matching-substring>
            </xsl:analyze-string>
        </File>
    </xsl:template>

</xsl:stylesheet>

XML输出

<File>
   <Rec>
      <Start>000</Start>
      <A>123</A>
      <B>234</B>
      <C>33</C>
      <End>99</End>
   </Rec>
   <Rec>
      <Start>03</Start>
      <A>123d</A>
      <B>234s</B>
      <End>992</End>
   </Rec>
   <Rec>
      <Start>a00</Start>
      <B>234</B>
      <C>33</C>
      <End>99</End>
   </Rec>
</File>

答案 1 :(得分:0)

我会通过标记化,然后分组来实现。

<xsl:variable name="raw" as="element()*">
  <xsl:for-each select="tokenize(normalize-space(unparsed-text('input.txt')), ',')">
    <xsl:element name="{substring-before(., ':')}">
      <xsl:value-of select="substring-after(., ':')"/>
    </xsl:element>
  </xsl:for-each>
</xsl:variable>
<File>
  <xsl:for-each-group select="$raw" group-starting-with="Start">
    <Rec>
      <xsl:copy-of select="current-group()"/>
    </Rec>
  </xsl:for-each-group>
</File>