【问题标题】:text to xml transforming using xslt使用 xslt 将文本转换为 xml
【发布时间】:2015-11-18 11:14:36
【问题描述】:

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

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>

编译错误如下:

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

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

【问题讨论】:

  • XSLT 旨在将 XML 输入转换为另一个 XML 模式或 HTML 或文本。为什么可能可以将文本转换为 XML(如果使用 XSLT 2.0),我会寻找更合适的工具。

标签: java xml text xslt-2.0


【解决方案1】:

先把线变成节点:

<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> 

【讨论】:

  • 谢谢你的回答,让我试着回复你。
  • 问题已更新,有什么方法可以将输入从 java 类传递给 xslt。
  • 只需声明&lt;xsl:param name="input" as="xs:string"/&gt;,并使用transformer.setParameter()将值从Java传递给参数。
【解决方案2】:

你可以使用 XSLT2.0 中的 unparsed-text 函数

For details use W3 specification for this function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 1970-01-01
    相关资源
    最近更新 更多