0

Using XSLT 3.0,

I have as input the following 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>

given values used for matching: (i use \t to define the tab separated nature of my input file)

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

i need to insert to all records that do not already have a PROPERTY tag, with the value of 06

Desired result:

 <?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>

What i have tried, adds the element property, even if it is already there, so i end up with two elements PROPERTY, in the same node, if it already exists. Could you give me an example implementation, i use SAXON latest release (9.8)

xsl: which adds an element, even when one exists:

<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>

Have been using the solution suggested with my real data, (which differ a lot from the example), and i face the following issue:

How could i also have a report that would let me know, which of the additions while they were to be done, according to the input file, were not inserted?

4

2 回答 2

0

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

  1. 模板应该匹配RECORD,而不是RECORD IDID是一个 不参与任何决策的属性)。

  2. 你的一般概念是好的:

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

  4. 当您指定XSLT 3.0时,甚至身份模板也可以替换为 (有点短) on-no-match="shallow-copy"

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

所以整个脚本如下所示:

<?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/上测试

于 2017-12-19T14:12:40.333 回答
0

几点观察:

(a) 在您的示例输出中,PROPERTY 元素已从记录 3 中删除。我在您对需求的描述中看不到任何解释原因的内容。

(b) 在您的需求声明中,“我需要插入到所有还没有属性标记的记录中,值为 06”这句话是不明确的。我的意思是,如果有一个属性“标签”(正确地,元素)的值不是 06,那么您应该插入另一个 PROPERTY 元素,但这似乎与您在其他地方所说的相矛盾。

(c) 您的代码有一个带有match="//*[local-name() = 'RECORD ID']". 您可以删除匹配模式开头的“//”,这是多余的。更重要的是,没有元素的本地名称等于“RECORD ID”——元素名称不能包含空格。所以模板规则永远不会匹配任何东西。

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

(e) 您已要求 XSLT 3.0 解决方案,但您的问题中没有任何需要 XSLT 3.0 的内容,实际上您自己的样式表显示 version="2.0"。

(f) 我看不出制表符分隔的参数文件在其中扮演什么角色。

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

于 2017-11-28T19:44:03.743 回答