2011-12-08 10 views
1

私はINIからXMLへの変換を行っていますが、INI構文は単純です。私はsed/awk/grepを探していませんが、これは本当にXMLツールで行うべきです。INIをXMLに変換しますか?または任意の汎用レガシーフラットファイル? XSL? xmlstarletまたはxsltprocから?

通常のXSLでこれを行うことはできますか? 私はXflatについて聞いたことがありますが、私はCでコンパイルされたツールからそれを行うことができますか? xsltprocやxmlstarletなど。

ジェネリックINI構文はこのようなものです...

このようなXMLになり
[section] 
option = values 

...

<section> 
<option>values</option> 
</section> 

すべてのヘルプは非常に高く評価されるだろう。

+0

XML/XSLTコードが正しく表示されるように正しくフォーマットしてください。ヒント:コードを選択し、 '{}'アイコンをクリックしてください。 –

+0

実際にiniファイルの特定のサンプルを提供する場合、あなたの質問はもっと注意を引くでしょう - あなたの仕事の一部(問題定義)を未完成にしておらず、あなたの読者に実際のサンプルを構築する負担をかけないでください。 –

+0

私はサンプルを提供しましたが、INIは文字通り簡単です。それらのINIブロックのページ全体。 – TechZilla

答えて

4

これは、通常のXSLを使って行うことができますか?

はい、XSLT 2.0はXSLT 1.0よりも多くの機能を備えています()。 a general LR(1) parserなどの非常に複雑なテキスト処理がXSLTで実装されており、specific grammars, such as JSONとXPathのパーサーを構築するために使用されています。正規表現(matches()を使用して許可したものを含めて具体的には、およそunparsed-text()を学ぶ

、様々なstring functionstokenize()replace())とも<xsl:analyze-string>命令。

XSLT 1.0には文字列関数(XPath 1.0で提供)もありますが、正規表現の機能/機能がなく、XSLT 2.0関数unparsed-text()などはありません。最も有用なXPath 1.0の文字列関数の中には:substring()substring-after()starts-with()string-length()concat()substring-before()、そして特にtranslate()機能。

Mads Hansenが彼の答えで説明したように、DTD内のエンティティを使ってファイルを "読む"ことができます。もう1つの方法は、変換を開始するプログラム内のファイルを読み取ってから、ファイルのコンテンツを文字列パラメータとして変換に渡すことです。

更新:完全な溶液が可能であるようにOPは現在、特定のデータを提供した:

この変換は、(使用されない)任意のXML文書に適用され
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

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

<xsl:variable name="vLines" as="xs:string*" select= 
    "tokenize($vText, '&#xD;?&#xA;')[.]"/> 

<xsl:variable name="vLineCnt" select="count($vLines)"/> 

<xsl:variable name="vSectLinesInds" as="xs:integer*" select= 
    "for $i in 1 to $vLineCnt 
    return 
     if(starts-with(normalize-space($vLines[$i]), '[')) 
     then $i 
     else() 
    "/> 

<xsl:variable name="vSectCnt" select="count($vSectLinesInds)"/> 

<xsl:template match="/"> 
    <xsl:for-each select="$vSectLinesInds"> 
    <xsl:variable name="vPos" select="position()"/> 
    <xsl:variable name="vInd" as="xs:integer" select="."/> 

    <xsl:variable name="vthisLine" as="xs:string" 
      select="$vLines[$vInd]"/> 

    <xsl:variable name="vNextSectInd" select= 
    "if($vPos eq $vSectCnt) 
     then 
      $vLineCnt +1 
     else 
      $vSectLinesInds[$vPos +1] 
    "/> 

    <xsl:variable name="vInnerLines" select= 
    "$vLines 
     [position() gt current() 
     and 
     position() lt $vNextSectInd 
     ] 

    "/> 

    <xsl:variable name="vName" select= 
    "tokenize($vthisLine, '\[|\]')[2]"/> 

    <xsl:element name="{$vName}"> 
    <xsl:for-each select="$vInnerLines"> 
     <xsl:variable name="vInnerParts" select= 
     "tokenize(., '[ ]*=[ ]*')"/> 

     <xsl:element name="{$vInnerParts[1]}"> 
     <xsl:value-of select="$vInnerParts[2]"/> 
     </xsl:element> 
    </xsl:for-each> 
    </xsl:element> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

とファイルであれば

[section1] 
option1 = values1 
option2 = values2 
option3 = values3 
option4 = values4 
option5 = values5 

[section2] 
option1 = values1 
option2 = values2 
option3 = values3 
option4 = values4 
option5 = values5 

[section3] 
option1 = values1 
option2 = values2 
option3 = values3 
option4 = values4 
option5 = values5 

C:\temp\delete\test.iniは、以下の内容を持っています必要な正しい結果が得られます。

<section1> 
    <option1>values1</option1> 
    <option2>values2</option2> 
    <option3>values3</option3> 
    <option4>values4</option4> 
    <option5>values5</option5> 
</section1> 
<section2> 
    <option1>values1</option1> 
    <option2>values2</option2> 
    <option3>values3</option3> 
    <option4>values4</option4> 
    <option5>values5</option5> 
</section2> 
<section3> 
    <option1>values1</option1> 
    <option2>values2</option2> 
    <option3>values3</option3> 
    <option4>values4</option4> 
    <option5>values5</option5> 
</section3> 
1

XSLT 2.0プロセッサを使用することができる場合は、フラットファイルをインポートできるunparsed-text()関数があります。

ファイルをインポートしたら、データ(正規表現、翻訳...)を処理するための従来の文字列ツールがXPath 2.0にあります。http://www.w3.org/TR/xpath-functions/#string-functionsを参照してください。

2

はい、あなたはそれがあなたのためのオプションがある場合、おそらく、XSLT 2.0でそうするために容易になるだろうXSLT

でプレーンテキストファイルを解析することができます。 XSLT 2.0で

:あなたが行に分割し、tokenize()をファイルを読むためにunparsed-text()機能を使用することができます。 XSLT 1.0で

<xsl:for-each select="tokenize(unparsed-text($in), '\r?\n')"> 
... 
</xsl:for-each> 

:あなたがいる限り、彼らは任意の文字/パターンが含まれていないとして(外部エンティティでテキストファイルを参照することによって、XMLファイルに組み込んで多くフラットテキストファイルを読み込むことができますXML解析エラーが発生する可能性があります)。ファイルからのテキストは、解析されるときにXMLファイルに含まれます。

<!DOCTYPE foo [ 
<!ENTITY bar SYSTEM "bar.txt"> 
]> 
<foo> 
&bar; 
</foo> 
+0

このテクニックは多くのファイルで有効ですが、< or & or ]]>を含むものではありません。また、XMLパーサーが特別に扱うさまざまなものには対応していません。 –

+0

@Michael Kay - はい、良い点。 XSLT 1.0エンティティソリューションの警告を追加しました。 –

関連する問題