Сохранять форматирование HTML в узле XML при преобразовании в CSV - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть несколько длинных файлов XML, которые включают форматирование HTML в некоторых узлах.Например:

<note encodinganalog="isadg361 marc500">
    <p>Published, with some changes, as "In Small Townlands" in <title render="italic">Death of a Naturalist</title> (1966).</p>
    <p>See also copy of "In Small Towlands" at reference <ref target="heaney.01.02.48" role="didid" actuate="onrequest">Heaney 1/2/48.</ref></p>
  </note>

Или:

<scopecontent encodinganalog="isadg331 marc520">
  <head>Scope and Content</head>
  <p>The Seamus Heaney Collection comprises typescript and manuscript poems, many of which were later pulished in <title render="italic">Death of a Naturalist</title> and<title render="italic"> Door into the Dark</title>. There is also a short story titled<title render="italic"> The Blackberry Gatherers</title> and 8 letters to Philip Hobsbaum, including discussion of Heaney's work and The Group meetings in Belfast.</p>
</scopecontent>

Или:

<altformavail type="isadg342 marc530">
<head>Copies in Other Formats</head>
<p>Many of the poems were published, sometimes with changes, in <bibref><title render="italic">Death of a Naturalist</title> <imprint>(Faber, <date normal="1966">1966)</date></imprint></bibref> and <bibref><title render="italic">Door into the Dark</title> <imprint>(Faber, <date normal="1969">1969).</date></imprint></bibref></p>
  </altformavail>

Во всех примерах я хотел бы сохранить все, что упоминается (<head>, <p>, <title> и т. Д.), Но когда я использую онлайн-инструменты, такие как http://www.convertcsv.com/xml-to-csv.htm или импортирую XML в Excel в качестве источника данных, теги в узлах становятся заголовками столбцов (например, в<note> узел <title render="italic">Death of a Naturalist</title> разделяется так, что заголовки и заголовки становятся заголовками столбцов, а их значения - «Смерть натуралиста» и «курсив».

XSLT уже применяется кXML для внесения незначительных изменений.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- 1. identity template copies everything as is -->
<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
</xsl:template>

<!-- 2. if there is an id attribute, delete it -->
<xsl:template match="unitid/@id" />

<!-- 3. move the value of the id attribute into the element value -->
<xsl:template match="unitid[@id]/text()">
    <xsl:value-of select="../@id | ../../@id" />
</xsl:template>

<!-- 4. create a <physloc> element inside <did> -->
<xsl:template match="did[not(physloc)]">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" />
        <physloc><xsl:value-of select="unitid" /></physloc>
    </xsl:copy>
</xsl:template>

Может ли этот XSLT быть перезаписан, чтобы сохранить форматирование для всех узлов, чтобы при преобразовании в CSV эти теги

Конечный результат:

    title, unitid, date, note, scopecontent, altformavail 
Death of a Naturalist , heaney.01.02.48 , 1966 , '<p>Published, with some changes, as "In Small Townlands" in <title render="italic">Death of a Naturalist</title> (1966).</p>
    <p>See also copy of "In Small Towlands" at reference <ref target="heaney.01.02.48" role="didid" actuate="onrequest">Heaney 1/2/48.</ref></p>' , '<head>Scope and Content</head>
      <p>The Seamus Heaney Collection comprises typescript and manuscript poems, many of which were later pulished in <title render="italic">Death of a Naturalist</title> and<title render="italic"> Door into the Dark</title>. There is also a short story titled<title render="italic"> The Blackberry Gatherers</title> and 8 letters to Philip Hobsbaum, including discussion of Heaney's work and The Group meetings in Belfast.</p>' , '<head>Copies in Other Formats</head>
    <p>Many of the poems were published, sometimes with changes, in <bibref><title render="italic">Death of a Naturalist</title> <imprint>(Faber, <date normal="1966">1966)</date></imprint></bibref> and <bibref><title render="italic">Door into the Dark</title> <imprint>(Faber, <date normal="1969">1969).</date></imprint></bibref></p>' 

Примечание: это не только теги <note>, <scopecontent> and <altformavail>, имеющие этот уровень форматирования, и он может применяться ко всемузлы в XML.

1 Ответ

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

Самым простым решением является создание самого CSV с использованием XSLT, поскольку это даст вам больший контроль над выходом.

С учетом следующего ввода:

<elements>
    <element unitId="heaney.01.02.48">
        <title>Death of a Naturalist</title>
        <date>1966</date>
        <note encodinganalog="isadg361 marc500">
            <p>
                Published, with some changes, as "In Small Townlands" in
                <title render="italic">Death of a Naturalist</title>
                (1966).
            </p>
            <p>
                See also copy of "In Small Towlands" at reference
                <ref target="heaney.01.02.48" role="didid" actuate="onrequest">Heaney
                    1/2/48.</ref>
            </p>
        </note>
        <scopecontent encodinganalog="isadg331 marc520">
            <head>Scope and Content</head>
            <p>
                The Seamus Heaney Collection comprises typescript and manuscript
                poems, many of which were later pulished in
                <title render="italic">Death of a Naturalist</title>
                and
                <title render="italic"> Door into the Dark</title>
                . There is also a short story titled
                <title render="italic"> The Blackberry Gatherers</title>
                and 8 letters to Philip Hobsbaum, including discussion of Heaney's
                work and The Group meetings in Belfast.
            </p>
        </scopecontent>
        <altformavail type="isadg342 marc530">
            <head>Copies in Other Formats</head>
            <p>
                Many of the poems were published, sometimes with changes, in
                <bibref>
                    <title render="italic">Death of a Naturalist</title>
                    <imprint>
                        (Faber,
                        <date normal="1966">1966)</date>
                    </imprint>
                </bibref>
                and
                <bibref>
                    <title render="italic">Door into the Dark</title>
                    <imprint>
                        (Faber,
                        <date normal="1969">1969).</date>
                    </imprint>
                </bibref>
            </p>
        </altformavail>
    </element>
</elements>

Вы можете использовать следующий XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <xsl:text>title,unitid,date,note,scopecontent,altformavail</xsl:text>
        <xsl:for-each select="elements/element">
            <!-- insert new line -->
            <xsl:text>&#xa;</xsl:text>
            <xsl:apply-templates select="./title" />
            <xsl:text>,</xsl:text>
            <xsl:apply-templates select="./@unitId" />
            <xsl:text>,</xsl:text>
            <xsl:apply-templates select="./date" />
            <xsl:text>,</xsl:text>
            <xsl:apply-templates select="./note" />
            <xsl:text>,</xsl:text>
            <xsl:apply-templates select="./scopecontent" />
            <xsl:text>,</xsl:text>
           <xsl:apply-templates select="./altformavail" />
       </xsl:for-each>

    </xsl:template>
    <xsl:template match="title|date|note|scopecontent|altformavail">
        <!-- surround the contents with quotes -->
        <xsl:text>'</xsl:text>
        <xsl:copy-of select="."/> 
        <xsl:text>'</xsl:text>
    </xsl:template>
</xsl:stylesheet>

Это создает CSV с сохранением разрывов строк и нескольких пробелов. Если мы хотим нормализовать пробелы, нам нужно немного углубиться в исходный XML:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" omit-xml-declaration="yes" />
    <xsl:template match="/">
        <xsl:text>title,unitid,date,note,scopecontent,altformavail</xsl:text>
        <xsl:for-each select="elements/element">
            <xsl:text>&#xa;</xsl:text>
            <xsl:apply-templates select="./title" />
            <xsl:text>,</xsl:text>
            <xsl:apply-templates select="./@unitId" />
            <xsl:text>,</xsl:text>
            <xsl:apply-templates select="./date" />
            <xsl:text>,</xsl:text>
            <xsl:apply-templates select="./note" />
            <xsl:text>,</xsl:text>
            <xsl:apply-templates select="./scopecontent" />
            <xsl:text>,</xsl:text>
            <xsl:apply-templates select="./altformavail" />
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="title|date|note|scopecontent|altformavail">
        <xsl:text>'</xsl:text>
        <xsl:apply-templates /> <!-- We'll define additional processing rules for each node inside -->
        <xsl:text>'</xsl:text>
    </xsl:template>

    <!-- When an element is encountered... -->
    <xsl:template match="*"> 
        <!-- ...output an element with the same name... -->
        <xsl:element name="{name()}" >
            <!-- ...and attributes... -->
            <xsl:copy-of select="./@*" />
            <!-- ...applying the rules for element and text nodes to whatever's inside -->
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>

    <!-- When a text node is encountered, print its content with spaces normalized  -->
    <xsl:template match="text()">
        <!-- If the node is empty, don't print anything -->
        <xsl:if test="normalize-space()">
            <xsl:value-of select="concat(normalize-space(), ' ')" />
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Если вам нужна дополнительная обработка текстового содержимого (например, экранирование запятых в столбцах CSV), измените concat(normalize-space(), ' ') в соответствии с вашими потребностями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...