使用xslt进行xml转换的文本

时间:2015-11-18 11:14:37

标签: java xml text xslt-2.0

我有一个以下数据格式的文本文件:

FIRSTNAME
Jhon
Rembo

FIRSTNAME
James
KARL

LASTNAME
PAUL
SAM
BOND

我正在尝试使用XSLT 2.0将其转换为以下XML格式

<?xml version="1.0" encoding="UTF-8"?>
<customers>
    <firstnames>
        <firstname>Jhon</firstname>
        <firstname>Rembo</firstname>
    </firstnames>
    <firstnames>
        <firstname>James</firstname>
        <firstname>KARL</firstname>
    </firstnames>
    <lastnames>
        <lastname>PAUL</lastname>
        <lastname>SAM</lastname>
        <lastname>BOND</lastname>       
    </lastnames>    
</customers>

任何提示或示例如何实现XML结果。

编辑:

我尝试过以下java代码:

final String TXT_PATH = "D:/TXT_one.txt";
final String XSLT_PATH = "D:/XSLT_one.xslt";
final String XML_PATH = "D:/test_xml_result_one.xml";

TransformerFactory tFactory = new net.sf.saxon.TransformerFactoryImpl();
Transformer transformer = tFactory.newTransformer(new StreamSource(new File(XSLT_PATH)));
transformer.transform(new StreamSource(new File(TXT_PATH)), new StreamResult(new File(XML_PATH)));

System.out.println("Output written to text file");

和XSLT文件:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 xmlns:my="my:my" exclude-result-prefixes="ext my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:variable name="lines" as="element()*">
      <xsl:for-each select="tokenize(unparsed-text($input), '\r?\n')">
        <line><xsl:value-of select="."/></line>
      </xsl:for-each>
  </xsl:variable>

  <results>
   <xsl:apply-templates select="$lines/*"/>
  </results>
 </xsl:template>

 <xsl:template match="text()" name="group">
 <xsl:param name="lines" select="."/>
    <xsl:for-each-group select="$lines[normalize-space()]" 
          group-starting-with="*[.=('FIRSTNAME', 'LASTNAME')]">
          <xsl:element name="{lower-case(.)}s">
            <xsl:for-each select="remove(current-group(), 1)">
              <xsl:element name="{lower-case(current-group()[1])}">
                <xsl:value-of select="."/>
              </xsl:element>
            </xsl:for-each>
          </xsl:element>
      </xsl:for-each-group> 
 </xsl:template>

</xsl:stylesheet>

编译错误如下:

  

xsl:for-each在XSLT_one.xslt的第9行第68列上的错误:
  XPST0008:尚未声明变量输入(或其声明为   不在范围内)

以什么方式将输入作为txt文件从java类传递?

2 个答案:

答案 0 :(得分:2)

首先将线条转换为节点:

<xsl:variable name="lines" as="element()*">
  <xsl:for-each select="tokenize(unparsed-text($input), '\r?\n')">
    <line><xsl:value-of select="."/></line>
  </xsl:for-each>
</xsl:variable>

然后将它们分组:

<xsl:for-each-group select="$lines[normalize-space()]" 
  group-starting-with="*[.=('FIRSTNAME', 'LASTNAME')]">
  <xsl:element name="{lower-case(.)}s">
    <xsl:for-each select="remove(current-group(), 1)">
      <xsl:element name="{lower-case(current-group()[1])}">
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:for-each>
  </xsl:element>
</xsl:for-each-group> 

为了完整性,这可以通过XSLT 3.0减少到:

<xsl:for-each-group 
   select="unparsed-text-lines($input)[normalize-space()]" 
   group-starting-with=".[.=('FIRSTNAME', 'LASTNAME')]">
   <xsl:element name="{lower-case(.)}s">
     <xsl:for-each select="tail(current-group())">
       <xsl:element name="{lower-case(current-group()[1])}">
         <xsl:value-of select="."/>
       </xsl:element>
     </xsl:for-each>
   </xsl:element>
</xsl:for-each-group> 

答案 1 :(得分:0)

您可以使用XSLT2.0中的非解析文本功能

For details use W3 specification for this function