XML输出,其中元素值作为标签名称,下一个后续元素值作为所创建标签的值

时间:2019-11-12 10:42:55

标签: xslt ibm-integration-bus extended-sql

我需要形成一个输出xml,其中需要将字段值作为标签,然后将随后的下一个字段值作为创建的标签的值。

<PrimaryKey>
    <PK1FeildName>CONNO</PK1FeildName>
    <PK1Value>001</PK1Value>
    <PK2FeildName>INNO</PK2FeildName>
    <PK2Value>123</PK2Value>
    <PK3FeildName>CONNO</PK3FeildName>
    <PK3Value>011</PK3Value>
</PrimaryKey>

预期输出:

<PrimaryKey>
  <CONNO>001</CONNO>
  <INNO>123</INNO>
  <CONNO>011</CONNO>
</PrimaryKey>

2 个答案:

答案 0 :(得分:1)

如果我们认为元素将始终成对出现,其中第一个元素的值是标签名称,第二个元素是值,则可以这样做:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="PrimaryKey">
      <xsl:element name="PrimaryKey">
          <xsl:apply-templates/>
      </xsl:element>
  </xsl:template>

  <xsl:template match="*">
    <xsl:if test="count(preceding-sibling::*) mod 2 = 0">
        <xsl:element name="{.}">
            <xsl:value-of select="following-sibling::*[1]"/>
        </xsl:element>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

您可以在这里尝试:https://xsltfiddle.liberty-development.net/bwdws3

编辑以回答评论

示例XML:

<Document>
    <PrimaryKey>
        <PK1FeildName>CONNO</PK1FeildName>
        <PK1Value>001</PK1Value>
        <PK2FeildName>INNO</PK2FeildName>
        <PK2Value>123</PK2Value>
        <PK3FeildName>CONNO</PK3FeildName>
        <PK3Value>011</PK3Value>
    </PrimaryKey>
    <PrimaryKey>
        <PK1FeildName>CONNO2</PK1FeildName>
        <PK1Value>0012</PK1Value>
        <PK2FeildName>INNO2</PK2FeildName>
        <PK2Value>1232</PK2Value>
        <PK3FeildName>CONNO2</PK3FeildName>
        <PK3Value>0112</PK3Value>
    </PrimaryKey>
</Document>

修改后的XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
      <xsl:element name="PrimaryKey">
          <xsl:apply-templates/>
      </xsl:element>
  </xsl:template>

  <xsl:template match="PrimaryKey/*">
    <xsl:if test="count(preceding-sibling::*) mod 2 = 0">
        <xsl:element name="{.}">
            <xsl:value-of select="following-sibling::*[1]"/>
        </xsl:element>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bwdws3/1

答案 1 :(得分:0)

出于完整性考虑,以下是使用ESQL而不是XSLT的解决方案:

CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
    -- Get a reference to the first instance of 'PK1FeildName'
    DECLARE refPK REFERENCE TO InputRoot.XMLNSC.PrimaryKey.PK1FeildName[1];
    WHILE LASTMOVE(refPK) DO
        -- remember the field name 
        DECLARE keyName CHARACTER FIELDVALUE(refPK);
        MOVE refPK NEXTSIBLING;

        -- create the next field in the output
        CREATE LASTCHILD OF OutputRoot.XMLNSC.Document.PrimaryKey TYPE NameValue NAME keyName VALUE FIELDVALUE(refPK);
        MOVE refPK NEXTSIBLING;
    END WHILE;

    RETURN TRUE;
END;

无论您使用XSL还是ESQL,我都建议您针对XSD验证传入的XML,因为映射代码取决于以特定顺序查看特定标记。您可以添加代码来检查标记名称,但是XSD验证是一个更简单的解决方案。