Вывод XML со значением элемента в качестве имени тега и значением следующего последующего элемента в качестве значения для созданного тега

Мне нужно сформировать выходной 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>

person Chandrika Deshpande    schedule 12.11.2019    source источник
comment
Я заметил, что вы добавили в этот пост тег esql. Вы используете IBM Integration Bus?   -  person kimbert    schedule 12.11.2019
comment
Да, я использую интеграционную шину IBM, но я пытался реализовать логику, читая имя поля, фиксируя его в выходной древовидной структуре, но я не могу получить тег и его соответствующее значение по мере необходимости ... На данный момент я работали над реализацией логики для имени поля и значений в двух разных древовидных структурах, но позже мне снова придется сравнивать ее на уровне подстроки, я не уверен, как это сделать дальше   -  person Chandrika Deshpande    schedule 12.11.2019
comment
Обратите внимание, что field пишется таким образом, а не feild. Вам решать, является ли это фактором вашей проблемы.   -  person Jonathan Leffler    schedule 22.11.2019


Ответы (2)


Если учесть, что элементы всегда будут появляться парами, где значение первого элемента - это имя тега, а второго - значение, тогда это сработает:

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

person Sebastien    schedule 12.11.2019
comment
Спасибо, Себастьян, просто мне нужно было спросить вас, как это работает, если у меня несколько случаев использования тега primarykey, нужно ли мне упоминать шаблон с именем основного корневого тега? Просто хотел понять, как работает шаблон, так как я новичок в Xslt. ‹Root› ‹PrimaryKey› ‹PK1FeildName› CONNO ‹/PK1 ‹FeildName› ‹PK1Value› 001 ‹/PK1Value› ‹PK2FeildName› INNO ‹/PK2FeildName›FeildName› / PK3FeildName ›‹PK3Value› 011 ‹/PK3Value› ‹/PrimaryKey› ‹/Root› - person Chandrika Deshpande; 12.11.2019
comment
См. Мой измененный ответ, чтобы учесть XML, который будет иметь более одного ‹PrimaryKey›. - person Sebastien; 12.11.2019
comment
Большое спасибо за помощь, Себастьян, всего один вопрос для моего обучения: «Follow-sibling :: * [1]» действует как значение конкретного поля, считываемого в цикле? - person Chandrika Deshpande; 13.11.2019
comment
В шаблоне match = PrimaryKey / * оператор if проверяет, является ли позиция элемента четным числом (т.е. первым элементом пары). Оператор following-sibling :: * [1] выбирает значение следующего элемента. Таким образом, первый элемент становится именем узла, а второй элемент становится значением. - person Sebastien; 13.11.2019
comment
Если на ваш вопрос ответят, закройте его, приняв ответ. - person Sebastien; 13.11.2019
comment
Этот постоянный подсчет предшествующих братьев и сестер обходится дорого; используйте вместо этого position(). И вы можете применять шаблоны выборочно к первому узлу в паре вместо тестирования каждого из них. Или вы можете использовать последнюю часть имени, чтобы отличить их друг от друга. - person michael.hor257k; 14.11.2019

Для полноты, вот решение, использующее 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, я бы рекомендовал вам проверять входящий XML на XSD, потому что код сопоставления зависит от просмотра определенных тегов в определенном порядке. Вы можете добавить код для проверки имен тегов, но проверка XSD - гораздо более простое решение.

person kimbert    schedule 14.11.2019
comment
Спасибо, Кимберт, это было очень полезно. - person Chandrika Deshpande; 15.11.2019