Arhn - архитектура программирования

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

Учитывая следующий файл xml в качестве входных данных:

<?xml ="1.0" encoding="UTF-8"?>
<TABLE NAME="TABLE.DB">
    <DATA RECORDS="2">
        <RECORD ID="1">
            <RECNO>1</RECNO>
            <SEQ>0</SEQ>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10355</NUMBER>
            <CN>PL</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>0</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <TOTALS>1</TOTALS>
            <SUB_A>Some (random) data.</SUB_A>
        </RECORD>
        <RECORD ID="2">
            <RECNO>2</RECNO>
            <SEQUENCE>0</SEQUENCE>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10356</NUMBER>
            <CN>PL 300 L</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>10</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <TOTALS>19837</TOTALS>
        </RECORD>
        <RECORD ID="3">
            <RECNO>3</RECNO>
            <SEQUENCE>0</SEQUENCE>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10357</NUMBER>
            <CN>PL 300 L</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>10</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <SUB_A>Some [more] data.</SUB_A>
        </RECORD>
    </DATA>
</TABLE>

Я хотел бы вставить данные в элемент SUB_A на основе следующих критериев: у меня есть файл, разделенный вкладками,

value A NUMBER  TOTALS

где значение A должно быть введено в элемент SUB_A с символом | в качестве разделителя, если SUB_A уже существует в записи, или должен быть создан, если он не существует. NUMBER и TOTALS — это те, которые нам нужны, чтобы сопоставить записи, в которых будет происходить преобразование. Значение TOTALS, иногда может вообще не существовать в нашем входном текстовом файле:

Итак, наш файл transform.txt выглядит так:

РЕДАКТИРОВАТЬ:

с помощью решения любезно г-н. Хоннен предложил с предложенными входными данными, и когда у меня есть входные данные:

value i'd like to add   10355   1
another) value i'd like to add  10357   19837
yet another value.] 10358
test    10354

я получаю следующую ошибку:

       Tree size: 113 nodes, 392 characters, 7 attributes
<line number="10355" totals="1">value i'd like to add</line><line number="10357" totals="19837">another) value i'd like to add</line><line number="10358" totals="">yet another value.]</line><line number="10354" totals="">test</line>
Error at char 6 in xsl:merge-source/@select on line 26 column 65 of merge.xsl:
  XTDE2220: Merge input for source line is not ordered according to merge key, detected at
  key value: ["10354", ""]
  in built-in template rule for /TABLE/DATA[1] in the unnamed mode
  at xsl:apply-templates (/merge.xsl#21)
     processing /TABLE
Merge input for source line is not ordered according to merge key, detected at key value: ["10354", ""]

Ожидаемый результат:

<?xml ="1.0" encoding="UTF-8"?>
<TABLE NAME="TABLE.DB">
    <DATA RECORDS="2">
        <RECORD ID="1">
            <RECNO>1</RECNO>
            <SEQ>0</SEQ>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10355</NUMBER>
            <CN>PL</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>0</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <TOTALS>1</TOTALS>
            <SUB_A>Some (random) data. | value i'd like to add</SUB_A>
        </RECORD>
        <RECORD ID="2">
            <RECNO>2</RECNO>
            <SEQUENCE>0</SEQUENCE>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10356</NUMBER>
            <CN>PL 300 L</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>10</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <TOTALS>19837</TOTALS>
            <SUB_A>(another) value i'd like to add</SUB_A>
        </RECORD>
        <RECORD ID="3">
            <RECNO>3</RECNO>
            <SEQUENCE>0</SEQUENCE>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10357</NUMBER>
            <CN>PL 300 L</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>10</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <SUB_A>Some [more] data. | [yet another value.]</SUB_A>
        </RECORD>
    </DATA>
</TABLE>

то, что я пробовал, сделало бы вопрос еще больше и не приблизило меня к тому, что я ищу ...

21.09.2017

  • Являются ли эти числовые значения порядка 3d такими, как в примере? Какой процессор XSLT 2.0 вы используете? Хотя существуют различные стратегии для решения, это может быть хорошей проблемой для Saxon 9.8 и нового элемента xsl:merge. В общем, я бы сначала предложил преобразовать данные, разделенные табуляцией, в XML, используя unparsed-text(-lines) и tokenize или analyze-string. 21.09.2017
  • Числовые значения упорядочены в той последовательности, в которой я сделал пример, но, очевидно, в реальном XML также есть записи, которые вообще не совпадают, поэтому между выбранными мной записями есть также другие промежуточные записи, которые не затронуто - преобразовано. Я бы предпочел такое руководство, я использую saxon, да, версия 9.8, поэтому я должен сначала преобразовать входной файл, или это можно сделать в той же таблице стилей xsl? 21.09.2017
  • Преобразование текстовых данных в XML можно выполнить в той же таблице стилей, которая объединяет данные. Что касается фактических данных и того TOTALS, который может отсутствовать, может ли он отсутствовать как во входных данных XML, так и в данных, разделенных табуляцией? Что произойдет, если в ЗАПИСИ есть определенное ЧИСЛО, соответствующее строке, а ИТОГО существует в ЗАПИСИ, но не в строке? 21.09.2017

Ответы:


1

Поэтому я попытался реализовать это с помощью xsl:merge из XSLT 3.0, таким образом, нелегко справиться с возможностью отсутствия итогового значения. вы не можете использовать ключ слияния для этой части сравнения. Кроме того, преобразование текстовых данных в XML-данные может испортить слияние, если есть какие-либо пробелы в дополнение к символам табуляции, например, в ваших примерах данных табуляции есть пробелы после последнего числа, что искажает ключ слияния, хотя это можно исправить с помощью normalize-space или, возможно, лучше, используя analyze-string вместо tokenize для извлечения данных.

То, что я придумал, это

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math"
    expand-text="yes" version="3.0">

    <xsl:param name="text-uri" as="xs:string">test2017092101.txt</xsl:param>

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="lines" as="element(line)*">
        <xsl:apply-templates select="unparsed-text-lines($text-uri)"/>
    </xsl:variable>

    <xsl:template match=".[. instance of xs:string]">
        <xsl:variable name="tokens" as="xs:string*" select="tokenize(., '&#9;')[normalize-space()]"/>
        <line number="{$tokens[2]}" totals="{$tokens[3]}">{$tokens[1]}</line>
    </xsl:template>

    <xsl:template match="TABLE/DATA">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:merge>
                <xsl:merge-source name="record" select="RECORD">
                    <xsl:merge-key select="NUMBER"/>
                    <xsl:merge-key select="string(TOTALS)"/>
                </xsl:merge-source>
                <xsl:merge-source name="line" select="$lines">
                    <xsl:merge-key select="@number"/>
                    <xsl:merge-key select="string(@totals)"/>
                </xsl:merge-source>
                <xsl:merge-action>
                    <xsl:if test="current-merge-group('record')">
                        <xsl:copy>
                            <xsl:apply-templates select="* except SUB_A"/>
                            <SUB_A>
                                <xsl:value-of select="SUB_A, current-merge-group()[2]" separator="|"
                                />
                            </SUB_A>
                        </xsl:copy>
                    </xsl:if>
                </xsl:merge-action>
            </xsl:merge>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Образец, который я пробовал,

value i'd like to add   10355   1
(another) value i'd like to add 10357   19837
[yet another value.]    10358

с вводом

<?xml version="1.0" encoding="UTF-8"?>
<TABLE NAME="TABLE.DB">
    <DATA RECORDS="2">
        <RECORD ID="0">
            <RECNO>0</RECNO>
            <SEQ>0</SEQ>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10354</NUMBER>
            <CN>PL</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>0</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <TOTALS>1</TOTALS>
            <SUB_A>Some random data not matched.</SUB_A>
        </RECORD>
        <RECORD ID="1">
            <RECNO>1</RECNO>
            <SEQ>0</SEQ>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10355</NUMBER>
            <CN>PL</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>0</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <TOTALS>1</TOTALS>
            <SUB_A>Some (random) data.</SUB_A>
        </RECORD>
        <RECORD ID="2">
            <RECNO>2</RECNO>
            <SEQUENCE>0</SEQUENCE>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10356</NUMBER>
            <CN>PL 300 L</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>10</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <SUB_A>Some random data not matched.</SUB_A>
        </RECORD>
        <RECORD ID="3">
            <RECNO>3</RECNO>
            <SEQUENCE>0</SEQUENCE>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10357</NUMBER>
            <CN>PL 300 L</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>10</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <TOTALS>19837</TOTALS>
        </RECORD>
        <RECORD ID="3">
            <RECNO>3</RECNO>
            <SEQUENCE>0</SEQUENCE>
            <DATE>17/12/1999 2:44:08 μμ</DATE>
            <ID>12/11/2015 3:15:25 μμ</ID>
            <NUMBER>10358</NUMBER>
            <CN>PL 300 L</CN>
            <PROPERTY>0</PROPERTY>
            <DAYS>10</DAYS>
            <CURRENTSTATUS>0</CURRENTSTATUS>
            <SUB_A>Some [more] data.</SUB_A>
        </RECORD>
    </DATA>
</TABLE>

и результат тогда

<?xml version="1.0" encoding="UTF-8"?>
<TABLE NAME="TABLE.DB">
   <DATA RECORDS="2">
      <RECORD>
         <RECNO>0</RECNO>
         <SEQ>0</SEQ>
         <DATE>17/12/1999 2:44:08 μμ</DATE>
         <ID>12/11/2015 3:15:25 μμ</ID>
         <NUMBER>10354</NUMBER>
         <CN>PL</CN>
         <PROPERTY>0</PROPERTY>
         <DAYS>0</DAYS>
         <CURRENTSTATUS>0</CURRENTSTATUS>
         <TOTALS>1</TOTALS>
         <SUB_A>Some random data not matched.</SUB_A>
      </RECORD>
      <RECORD>
         <RECNO>1</RECNO>
         <SEQ>0</SEQ>
         <DATE>17/12/1999 2:44:08 μμ</DATE>
         <ID>12/11/2015 3:15:25 μμ</ID>
         <NUMBER>10355</NUMBER>
         <CN>PL</CN>
         <PROPERTY>0</PROPERTY>
         <DAYS>0</DAYS>
         <CURRENTSTATUS>0</CURRENTSTATUS>
         <TOTALS>1</TOTALS>
         <SUB_A>Some (random) data.|value i'd like to add</SUB_A>
      </RECORD>
      <RECORD>
         <RECNO>2</RECNO>
         <SEQUENCE>0</SEQUENCE>
         <DATE>17/12/1999 2:44:08 μμ</DATE>
         <ID>12/11/2015 3:15:25 μμ</ID>
         <NUMBER>10356</NUMBER>
         <CN>PL 300 L</CN>
         <PROPERTY>0</PROPERTY>
         <DAYS>10</DAYS>
         <CURRENTSTATUS>0</CURRENTSTATUS>
         <SUB_A>Some random data not matched.</SUB_A>
      </RECORD>
      <RECORD>
         <RECNO>3</RECNO>
         <SEQUENCE>0</SEQUENCE>
         <DATE>17/12/1999 2:44:08 μμ</DATE>
         <ID>12/11/2015 3:15:25 μμ</ID>
         <NUMBER>10357</NUMBER>
         <CN>PL 300 L</CN>
         <PROPERTY>0</PROPERTY>
         <DAYS>10</DAYS>
         <CURRENTSTATUS>0</CURRENTSTATUS>
         <TOTALS>19837</TOTALS>
         <SUB_A>(another) value i'd like to add</SUB_A>
      </RECORD>
      <RECORD>
         <RECNO>3</RECNO>
         <SEQUENCE>0</SEQUENCE>
         <DATE>17/12/1999 2:44:08 μμ</DATE>
         <ID>12/11/2015 3:15:25 μμ</ID>
         <NUMBER>10358</NUMBER>
         <CN>PL 300 L</CN>
         <PROPERTY>0</PROPERTY>
         <DAYS>10</DAYS>
         <CURRENTSTATUS>0</CURRENTSTATUS>
         <SUB_A>Some [more] data.|[yet another value.]</SUB_A>
      </RECORD>
   </DATA>
</TABLE>

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

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

<xsl:template match=".[. instance of xs:string]">
    <xsl:variable name="groups" select="analyze-string(., '([^0-9]*?)\s*([0-9]+)(\s*([0-9]+))?')//*:group"/>
    <line number="{$groups[2]}" totals="{$groups[4]}">{$groups[1]}</line>
</xsl:template>

который пытается использовать analyze-string вместо tokenize, но предполагает, что первый столбец не содержит цифр, а второй и необязательный третий состоят из цифр.

21.09.2017
  • @sadoyc, я добавил образцы данных, которые я тестировал, попробуйте проверить это и адаптировать код, если ваши данные отличаются, я не собираюсь загружать файлы rar. Если у вас все еще есть проблемы, попробуйте отредактировать свой вопрос с минимальными примерами, пытаясь проиллюстрировать проблему. 22.09.2017
  • Проблема на моей стороне, используя версию .net, в Windows 10, версию 9.8HE, с вашими образцами данных, а xml остается незатронутым. 22.09.2017
  • Вы установили параметр <xsl:param name="text-uri" as="xs:string">test2017092101.txt</xsl:param> на имя файла или URL-адрес текстового файла? Можете ли вы добавить шаблон <xsl:template match="/"><xsl:message select="$lines"/><xsl:apply-templates/></xsl:template> для проверки правильности преобразования текстовых файлов в элементы XML? 22.09.2017
  • ‹номер строки= итоги=›значение, которое я хотел бы добавить 10355 1‹/строка›‹номер строки= итоги=›(другое) значение, которое я хотел бы добавить 10357 19837‹/строка›‹номер строки= итоги=› [еще одно значение.] 10358‹/строка›, вывод, который я получаю в консоли, после добавления вашего любезно предложенного шаблона, точно ниже ‹xsl:param name=text-uri as=xs:string›test2017092101.txt‹/xsl: параметр› 22.09.2017
  • Таким образом, токенизация оказывается хрупкой, по крайней мере, при копировании образца из или в сообщение stackoverflow. Я думаю, что процесс преобразования текста в XML мог бы быть более надежным, используя analyze-string вместо tokenize, но весь формат этого текста до сих пор недоопределен, чтобы написать хороший шаблон регулярного выражения. Может ли текст перед двумя числами содержать какие-либо цифры? 22.09.2017
  • есть значение вроде 9η έκδ., но я могу легко заменить его на девятьη έκδ., поэтому у нас вообще нет цифр в первом столбце, если это поможет, или я могу преобразовать ввод, возможно, в два отдельных файла? нам не нужно использовать этот третий столбец, который вызывает проблемы, и существует только менее чем в 10 случаях, поэтому мы можем забыть о совпадении ИТОГОВ и искать только ЧИСЛА 22.09.2017
  • Что ж, пустые атрибуты в line number="" totals="" предполагают, что второй и третий столбцы не были обнаружены. Посмотрите добавленный шаблон в конце ответа и попробуйте использовать его вместо шаблона в полной таблице стилей и проверьте, имеют ли элементы line атрибуты со значениями из текстового файла. 22.09.2017
  • я попытался с еще одной строкой данных в txt-файле, и я получаю ошибку, которую я добавил в свой вопрос, используя ваш xsl и ваши входные данные. В реальных данных я сталкиваюсь с той же ошибкой. 23.09.2017
  • Если значения не упорядочены, вам нужно будет установить sort-before-merge="yes" в источниках слияния. 23.09.2017
  • спасибо, а в какой строке и как бы вы предложили это изменить? 23.09.2017
  • Если текстовый файл не упорядочен, используйте <xsl:merge-source name="line" select="$lines" sort-before-merge="yes">, если XML также не упорядочен, добавьте тот же атрибут и к другому xsl:merge-source. 23.09.2017
  • Может ли кто-нибудь сказать мне, как я могу сохранить ‹RECORD ID=0›, ‹RECORD ID=1›, ‹RECORD ID=2› в выходном файле? 05.10.2017
  • Я думаю, что вместо <xsl:copy><xsl:apply-templates select="* except SUB_A"/> должно быть ``‹xsl:copy›‹xsl:apply-templates select=@*, * кроме SUB_A/›`, чтобы скопировать любые атрибуты. 05.10.2017
  • сработало, кроме того, выходной xml был бы хорош, если бы его можно было отсортировать на основе RECORD ID 05.10.2017
  • Я думаю, вам лучше задать новый вопрос, четко указав, хотите ли вы сортировать по атрибуту ID (который, кажется, является числом) или по элементу ID (который, кажется, является некоторым форматом даты). 05.10.2017
  • только что опубликовал новый слегка измененный вопрос, спасибо, stackoverflow.com/questions/46588096/ 05.10.2017
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..