У меня есть некоторые текстовые файлы фиксированной длины для обработки, и выход должен быть структурированным XML-файлом.Формат этих текстовых файлов указан в XML.
Тримические части:
- Спецификация формата содержит вложенную структуру (элемент
StructFormat
может содержать StructFormat
) - структура может повторяться (используйте атрибут
repeat
StructFormat, например repeat='4'
).
Вот пример спецификации формата:
<?xml version='1.0' encoding='windows-1252'?>
<MessageFormat name='NewMessageFormat' version='2.02'>
<FieldFormat name='G-TRA-MESSAGE-ID' type='String' delimOptional='y' length='18' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
<StructFormat name='G-TAFT-HEAD-DAT' delimOptional='y'>
<FieldFormat name='G-AFT-FIP-DATUM' type='String' delimOptional='y' length='10' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
<FieldFormat name='G-AFT-FIP-ZEIT' type='String' delimOptional='y' length='8' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
</StructFormat>
<StructFormat name='G-TAFT-KUNDEN' delimOptional='y' repeat='2'>
<FieldFormat name='G-AKU-LDSGVNR' type='String' delimOptional='y' length='6' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
<FieldFormat name='G-AKU-KDSGVNR' type='String' delimOptional='y' length='10' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
</StructFormat>
<StructFormat name='G-TFGB-WGN-AN-LB' delimOptional='y' repeat='3'>
<FieldFormat name='G-ZA-WGN-FUNK-CODE' type='String' delimOptional='y' length='1' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
<FieldFormat name='G-FGB-WGN-RIV-CODE' type='String' delimOptional='y' length='2' strlenInChars='y' pad='0' padType='leading' trimLeading=' ' trimTrailing=' '/>
<StructFormat name='G-FSB-SONDERBEH-CD' delimOptional='y' repeat='5'>
<FieldFormat name='G-FSB-SONDERBEH-CD' type='String' delimOptional='y' length='2' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
</StructFormat>
<StructFormat name='G-TFGB-GUT-AN-LB' delimOptional='y' repeat='4'>
<FieldFormat name='G-FGB-GGT-ZETT-NR-1' type='String' delimOptional='y' length='4' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
<FieldFormat name='G-FGB-GGT-ZETT-NR-2' type='String' delimOptional='y' length='4' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
<FieldFormat name='G-FGB-GGT-ZETT-NR-3' type='String' delimOptional='y' length='4' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
</StructFormat>
<FieldFormat name='G-FBD-PRIO-KENNZ' type='String' delimOptional='y' length='1' strlenInChars='y' trimLeading=' ' trimTrailing=' '/>
</StructFormat>
</MessageFormat>
И образец текста:
G-TRA-MESSAGE-ID G-AFT-FIP-G-AFT-FIG-AKU-G-AKU-KDSGG-AKU-G-AKU-KDSGGG-G-G-G-G-G-G-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGGGG-G-G-G-G-G-G-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGGGG-G-G-G-G-G-G-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG-FGG
Таким образом, ожидаемый результат должен быть следующим:
<?xml version="1.0" encoding="UTF-8"?>
<NewMessageFormat>
<G-TRA-MESSAGE-ID>G-TRA-MESSAGE-ID</G-TRA-MESSAGE-ID>
<G-TAFT-HEAD-DAT>
<G-AFT-FIP-DATUM>G-AFT-FIP-</G-AFT-FIP-DATUM>
<G-AFT-FIP-ZEIT>G-AFT-FI</G-AFT-FIP-ZEIT>
</G-TAFT-HEAD-DAT>
<G-TAFT-KUNDEN>
<G-AKU-LDSGVNR>G-AKU-</G-AKU-LDSGVNR>
<G-AKU-KDSGVNR>G-AKU-KDSG</G-AKU-KDSGVNR>
</G-TAFT-KUNDEN>
<G-TAFT-KUNDEN>
<G-AKU-LDSGVNR>G-AKU-</G-AKU-LDSGVNR>
<G-AKU-KDSGVNR>G-AKU-KDSG</G-AKU-KDSGVNR>
</G-TAFT-KUNDEN>
<G-TFGB-WGN-AN-LB>
<G-ZA-WGN-FUNK-CODE>G</G-ZA-WGN-FUNK-CODE>
<G-FGB-WGN-RIV-CODE>G-</G-FGB-WGN-RIV-CODE>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-FBD-PRIO-KENNZ>G</G-FBD-PRIO-KENNZ>
</G-TFGB-WGN-AN-LB>
<G-TFGB-WGN-AN-LB>
<G-ZA-WGN-FUNK-CODE>G</G-ZA-WGN-FUNK-CODE>
<G-FGB-WGN-RIV-CODE>G-</G-FGB-WGN-RIV-CODE>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-FBD-PRIO-KENNZ>G</G-FBD-PRIO-KENNZ>
</G-TFGB-WGN-AN-LB>
<G-TFGB-WGN-AN-LB>
<G-ZA-WGN-FUNK-CODE>G</G-ZA-WGN-FUNK-CODE>
<G-FGB-WGN-RIV-CODE>G-</G-FGB-WGN-RIV-CODE>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>
<G-FSB-SONDERBEH-CD>G-</G-FSB-SONDERBEH-CD>
</G-FSB-SONDERBEH-CD>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-TFGB-GUT-AN-LB>
<G-FGB-GGT-ZETT-NR-1>G-FG</G-FGB-GGT-ZETT-NR-1>
<G-FGB-GGT-ZETT-NR-2>G-FG</G-FGB-GGT-ZETT-NR-2>
<G-FGB-GGT-ZETT-NR-3>G-FG</G-FGB-GGT-ZETT-NR-3>
</G-TFGB-GUT-AN-LB>
<G-FBD-PRIO-KENNZ>G</G-FBD-PRIO-KENNZ>
</G-TFGB-WGN-AN-LB>
</NewMessageFormat>
Мой подход состоит в том, чтобы использовать спецификацию формата XML в качестве источника XML, а затем текст передается в качестве строкового параметра в таблицу стилей XLST и использовать встроенный XSLT.Шаблон для обработки каждого узла элемента.Вот моя таблица стилей:
<?xml version="1.0" encoding="UTF-8"?>
<?altova_samplexml file:///D:/Entwicklung/xslt/Test_MFL.xml?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="text"/>
<xsl:template match="/">
<xsl:apply-templates select="element()"/>
</xsl:template>
<xsl:template name="StructFormat_withoutRepeat" match="StructFormat">
<xsl:element name="{./@name}">
<xsl:apply-templates select="element()"/>
</xsl:element>
</xsl:template>
<xsl:template name="StructFormat" match="StructFormat[@repeat]">
<xsl:variable name="repeat" select="./@repeat"/>
<xsl:variable name="Name" select="current()/@name"/>
<xsl:for-each select="1 to $repeat">
<xsl:element name="{$Name}">
<xsl:apply-templates select="element()"/>
</xsl:element>
<!--<xsl:call-template name="StructFormat_withoutRepeat"/>-->
</xsl:for-each>
</xsl:template>
<xsl:template name="FieldFormat" match="FieldFormat">
<xsl:variable name="fieldName" select="./@name"/>
<xsl:element name="{./@name}">
<xsl:value-of select="fn:substring($text,(/MessageFormat//FieldFormat[./@name = $fieldName]/preceding::FieldFormat/@length), ./@length)"/>
</xsl:element>
<xsl:apply-templates select="element()"/>
</xsl:template>
</xsl:stylesheet>
Однако она не работает для повторного strcuture.Проблема в строках:
<xsl:for-each select="1 to $repeat">
<xsl:element name="{$Name}">
<xsl:apply-templates select="element()"/>
</xsl:element>
<!--<xsl:call-template name="StructFormat_withoutRepeat"/>-->
</xsl:for-each>
Может кто-нибудь подсказать, пожалуйста, как решить эту проблему?
Спасибо большое!Dingjun