根据记录匹配条件向元素添加数据,如果不存在则创建一个 [英] add data to an element, or create one if it doesnot exist, based on record matching criteria

查看:18
本文介绍了根据记录匹配条件向元素添加数据,如果不存在则创建一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下 xml 文件作为输入:

Given the following xml file as input:

<?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 元素中:我有一个制表符分隔的文件,

I would like to insert data into SUB_A element, based on the following criteria: I have in a tab separated file,

value A NUMBER  TOTALS

其中必须在 SUB_A 元素中输入值 A,并带有 |作为分隔符,如果记录中已经存在SUB_A,或者如果不存在则创建.NUMBER 和 TOTALS 是我们需要的,以便在转换将发生的记录上进行匹配.有时,在我们的输入 txt 文件中,值 TOTALS 可能根本不存在:

where value A must be entered in the SUB_A element, with a | as a separator, if SUB_A already exists in the record, or to be created, if it does not exist. NUMBER, and TOTALS, are the ones we need, in order to make our match, on the records that the transformation will take place. The value TOTALS, may not exist, at all, sometimes, in our input txt file:

所以我们的transform.txt文件看起来像:

So our transform.txt file looks like:

请使用解决方案先生.Honnen 建议,建议输入数据,当我有输入时:

using the solution kindly mr. Honnen suggested, with the input data suggested, and when i have as input:

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>

我所尝试的,会使问题变得更大,并没有让我接近我想要的......

what I have tried, would make the question even larger, and has not gotten me close to whatIlook for...

推荐答案

所以我尝试使用 xsl:merge 来自 XSLT 3.0,处理缺少总计值的可能性并不容易,因为这样您就不能在比较的那部分使用合并键.此外,如果除了制表符之外还有任何空格,将文本数据转换为 XML 数据很容易弄乱合并,例如,在您的示例制表符数据中,最后一个数字后面有空格,这会弄乱合并键,虽然这可以通过使用 normalize-space 来解决,或者通过使用 analyze-string 而不是 tokenize 来提取数据可能更好.

So I have tried to implement that using xsl:merge from XSLT 3.0, it is not easy to deal with the possibility of a missing totals value as that way you can't use a merge key for that part of the comparison. Also converting the textual data to XML data is prone to mess up the merging if there is any white space additional to the tab characters, for instance in your sample tab data there is white space after the last number and that messes up the merge key, although that could be fixed with normalize-space use or perhaps better by using analyze-string instead of tokenize to extract the data.

我想到的是

<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 的代码将保持不变.

It should of course also be possible to use grouping instead of merging to solve that. The code to transform the tabular data to XML would remain the same.

这有点乱,但不要在注释中交换代码尝试替换模板以使用

This is getting a bit messy but to not interchange code in comments try to replace the template to create the line elements with

<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 但假设第一列不包含任何数字,第二列和可选的第三列由数字组成.

that tries to use analyze-string instead of tokenize but assumes the first column contains no no digits and the second and optional third are composed of digits.

这篇关于根据记录匹配条件向元素添加数据,如果不存在则创建一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆