XSL: преобразование XML в CSV, анализ атрибута - PullRequest
0 голосов
/ 02 мая 2018

Я конвертирую файл XML в файл CSV в XSLT 3.0, но обрабатываю только определенные узлы. Один из узлов является атрибутом с несколькими значениями, разделенными пробелами, и я хочу разбить каждое из этих значений на отдельную строку в целевом CSV-файле.

Пример исходного XML-файла:

<corpus>
 <deposition>
    <deposition-number n="dep1"/>
    <text>
      <seg n="seg1">Lorem ipsum dolor sit amet, <persName name="personA" ana="foo1 foo2">some foo person</persName> 
        adipiscing elit. Vivamu ultrices consequat facilisis. 
        Suspendisse a odio in lobortis. Aenean <persName name="personG" ana="foo2">some foo person</persName>
        non dui scelerisque, rutrum est at, cursus sem.</seg>
      <seg n="seg2">Ut pharetra <persName name="personF" ana="foo9">some foo person</persName>bibendum ipsum, portitor 
        velit pharetra quis. Aeneano purus. Praesent 
        aliquam viverra tellus.</seg>
     </text>
  </deposition>
  <deposition>
    <deposition-number n=""dep2"/>
    <text>
     <seg n="seg3">Curabitur pulvinar leo eget. Orci varius 
        natoque penatibus et magnis <persName name="personD" ana="foo2 foo3 foo8">some foo person</persName>montes, 
        nascetur ridiculus mus.</seg>
    </text>
  </deposition>
</corpus>

В настоящее время я могу вывести этот неудовлетворительный результат в CSV, где @ana находится в последнем поле:

 dep1~seg1~personA~foo1 foo2
 dep1~seg1~personG~foo2
 dep1~seg2~personF~foo9
 dep1~seg3~personD~foo2 foo3 foo8

С XSL, который выглядит следующим образом:

<xsl:template match="/">
    <xsl:for-each select="persName">
        <xsl:value-of select="ancestor::deposition-number/@n"/>
        <xsl:text>~</xsl:text>
        <xsl:value-of select="ancestor::seg/@n"/>
        <xsl:text>~</xsl:text>
        <xsl:value-of select="@name"/>
        <xsl:text>~</xsl:text>
        <xsl:value-of select="@ana"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template>

Но я хочу вывести это, где @ana разбит на отдельные строки:

 dep1~seg1~personA~foo1
 dep1~seg1~personA~foo2
 dep1~seg1~personG~foo2
 dep1~seg2~personF~foo9
 dep1~seg3~personD~foo2
 dep1~seg3~personD~foo3
 dep1~seg3~personD~foo8

Я пытался посмотреть на токенизацию, но если она способна решить эту проблему, я не уверен, как это сделать. Я не знаю, как разобрать @ana и пройтись по нему.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

С XSLT 3 вы можете маркировать значения и отправлять их в шаблон:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="3.0">

  <xsl:output method="text"/>

  <xsl:template match="/">
      <xsl:apply-templates select="//persName"/>
  </xsl:template>

  <xsl:template match="persName">
     <xsl:apply-templates select="tokenize(@ana, '\s+')">
         <xsl:with-param name="data" select="ancestor::deposition/deposition-number/@n, ancestor::seg/@n, @name"/>
     </xsl:apply-templates>
  </xsl:template>

  <xsl:template match=".[. instance of xs:string]">
      <xsl:param name="data"/>
      <xsl:value-of select="$data, ." separator="~"/>
      <xsl:text>&#10;</xsl:text>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / bdxtpS / 1

0 голосов
/ 02 мая 2018

Вместо этого попробуйте этот шаблон, который использует tokenize для разделения атрибута и вывода одной строки для каждого значения

<xsl:template match="/">
    <xsl:for-each select="//persName">
        <xsl:variable name="pers" select="." />
        <xsl:for-each select="tokenize(@ana, ' ')">
            <xsl:value-of select="$pers/ancestor::deposition/deposition-number/@n"/>
            <xsl:text>~</xsl:text>
            <xsl:value-of select="$pers/ancestor::seg/@n"/>
            <xsl:text>~</xsl:text>
            <xsl:value-of select="$pers/@name"/>
            <xsl:text>~</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

(Обратите внимание, что deposition-number не является предком persName в вашем XML)

Или, чтобы немного упростить это, попробуйте это ...

<xsl:template match="/">
    <xsl:for-each select="//persName">
        <xsl:variable name="pers" select="." />
        <xsl:for-each select="tokenize(@ana, ' ')">
            <xsl:value-of select="($pers/ancestor::deposition/deposition-number/@n, $pers/ancestor::seg/@n, $pers/@name, .)" separator="~"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...