Преобразовать INI в XML? ИЛИ какой-нибудь общий устаревший файл? XSL? из xmlstarlet или xsltproc? - PullRequest
1 голос
/ 08 декабря 2011

Я ищу какой-нибудь преобразование из INI в XML, синтаксис INI прост. Я не смотрю на sed / awk / grep, это действительно должно быть сделано в инструментах XML.

Можно ли это сделать с помощью обычного XSL? Я слышал о Xflat, но можно ли это сделать с помощью инструментов, скомпилированных в C? Например, xsltproc или xmlstarlet.

Общий синтаксис INI похож на это ...

[section]
option = values

который был бы в xml, как это ...

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

Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

4 голосов
/ 08 декабря 2011

Можно ли это сделать с обычным XSL?

Да, и XSLT 2.0 предоставляет больше возможностей, чем XSLT 1.0 для обработки текста .Очень сложная обработка текста была реализована в XSLT, включая общий анализатор LR (1) , используемый для построения синтаксических анализаторов для определенных грамматик, таких как JSON и XPath.

В частности, вы узнаете о unparsed-text(), различных строковых функциях включая те, которые позволяют использовать регулярные выражения (matches(), tokenize() и replace()), а также инструкция <xsl:analyze-string>.

XSLT 1.0 также имеет строковые функции (как предусмотрено в XPath 1.0), однако в нем отсутствуют регулярные выражения capabilty / functions и нет ничего такого, как функция XSLT 2.0 unparsed-text().Среди наиболее полезных строковых функций XPath 1.0: substring(), substring-before(), substring-after(), starts-with(), string-length(), concat(), и особенно функция translate().

Можно «прочитать» файл, используя объект в DTD, как Мадс Хансенобъяснил в своем ответе.Другой способ - прочитать файл в программе, которая инициирует преобразование, а затем передать содержимое файла в качестве строкового параметра преобразованию.

Обновление : OP теперь предоставил конкретные данные, так что возможно полное решение:

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

, когда это преобразование применяется к любому документу XML (не используется) и если файл в C:\temp\delete\test.ini имеетследующее содержание :

[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

желаемый, правильный результат :

<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>
2 голосов
/ 08 декабря 2011

Да, вы можете анализировать простой текстовый файл в XSLT

Вероятно, было бы проще сделать это в XSLT 2.0, если бы это был вариант для вас.

В XSLT 2.0, : вы можете использовать функцию unparsed-text () , чтобы прочитать файл, tokenize () , чтобы разбить его на строки.

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

В XSLT 1.0 : вы можете прочитать множество простых текстовых файлов, включив их в XML-файл, сославшись на текстовый файл с внешней сущностью (если они не содержат любые символы / шаблоны, которые могут привести к ошибкам синтаксического анализа XML). Текст из файла будет включен в файл XML при его разборе.

<!DOCTYPE foo [
<!ENTITY bar SYSTEM "bar.txt">
]>
<foo>
&bar;
</foo>
1 голос
/ 08 декабря 2011

Если вы можете использовать процессор XSLT 2.0, у вас есть функция unparsed-text(), которая может импортировать плоские файлы.

После того, как файл импортирован, в XPath 2.0 у вас есть традиционные строковые инструменты для обработки ваших данных (регулярное выражение, перевод ...), см. http://www.w3.org/TR/xpath-functions/#string-functions.

...