根据匹配条件,向节点添加元素(如果不存在)

时间:2017-11-21 12:43:44

标签: xslt-3.0

使用XSLT 3.0,

我输入以下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>
                <ORDER>10355</ORDER>
                <CN>PL</CN>
                <PROPERTY>06</PROPERTY>
            </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>
                <ORDER>000026672</ORDER>
                <CN>PL 300 L</CN>
            </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>
            </RECORD>
        </DATA>
    </TABLE>

给定用于匹配的值: (我使用\ t来定义输入文件的制表符分隔性质)

"10355"\t"PL"
"000026672"\t"PL 300 L"

我需要插入所有尚未拥有PROPERTY标记的记录,其值为06

期望的结果:

 <?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>
                <ORDER>10355</ORDER>
                <CN>PL</CN>
                <PROPERTY>06</PROPERTY>
            </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>
                <ORDER>000026672</ORDER>
                <CN>PL 300 L</CN>
                <PROPERTY>06</PROPERTY>
            </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>
            </RECORD>
        </DATA>
    </TABLE>

我尝试过,添加了element属性,即使它已经存在,所以我最终在同一节点中有两个元素PROPERTY,如果它已经存在的话。你能给我一个示例实现,我使用SAXON最新版本(9.8)

xsl:添加一个元素,即使存在一个元素:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="xsl exsl xs">
    <xsl:output method="xml" version="1.0" indent="yes" encoding="utf-8" />
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="//*[local-name() = 'RECORD ID']">
        <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
            <xsl:choose>
                <xsl:when test="not(PRODUCT)">
                    <PRODUCT><xsl:value-of select="98"/></PRODUCT>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy><xsl:value-of select="98"/></xsl:copy>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

一直使用我的真实数据建议的解决方案(与示例有很大不同),我面临以下问题:

我怎么能有一个报告让我知道,根据输入文件,哪些添加内容没有插入?

2 个答案:

答案 0 :(得分:0)

一些观察结果:

(a)在您的示例输出中,PROPERTY元素已从记录3中删除。我无法在您的要求说明中看到解释原因的任何内容。

(b)在您的要求声明中,句子&#34;我需要插入所有尚未拥有PROPERTY标签的记录,其值为06&#34;很暧昧。我会这样说,如果有一个PROPERTY&#39;标签&#39; (正确的,元素)的值不是06,那么你应该插入另一个PROPERTY元素,但这似乎与你在别处说的相矛盾。

(c)您的代码具有match="//*[local-name() = 'RECORD ID']"的模板规则。您可以删除&#34; //&#34;在比赛模式开始时,它是多余的。更重要的是,没有元素的本地名称等于&#34;记录ID&#34; - 元素名称不能包含空格。因此,模板规则永远不会匹配任何内容。

(d)假设此模板规则旨在匹配RECORD元素,您当然不希望xsl:copy在xsl中:否则,因为这将创建整个RECORD的嵌套副本。

(e)您已经要求提供XSLT 3.0解决方案,但您的问题中没有任何内容需要XSLT 3.0,事实上您自己的样式表说版本=&#34; 2.0&#34;

(f)我无法看到制表符分隔的参数文件在其中扮演的角色。

简而言之,在任何人开始编写任何代码之前,需要进行大量的澄清。

答案 1 :(得分:0)

您的解决方案需要进行一些更改:

  1. 模板与RECORD匹配,而不是RECORD IDID属性,不参与任何决定。)

  2. 您的一般概念还可以:

    • 复制起始标记(<RECORD>),
    • 将模板应用于当前RECORD
    • 的内部
    • 检查PROPERTY(不是PRODUCT)元素是否缺席(在 当前RECORD),
    • 如果是(缺席),则输出具有所需值的PROPERTY元素
    • 复制结束标记(</RECORD>)。
  3. 我删除了otherwise部分(不需要)并将choose更改为 一个if ..

  4. 在指定 XSLT 3.0 时,即使身份模板也可以 替换为(稍短)on-no-match="shallow-copy"

  5. 我还在您的源XML中添加了version。否则它的格式不正确。

  6. 所以整个脚本可能如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes"/>
      <xsl:strip-space elements="*"/>
      <xsl:mode on-no-match="shallow-copy"/>
    
      <xsl:template match="RECORD">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
            <xsl:if test="not(PROPERTY)">
              <PROPERTY>06</PROPERTY>
            </xsl:if>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    

    http://xsltfiddle.liberty-development.net/

    上进行测试