XSLT-преобразование, заменяющее вхождение элементов href путем копирования другого элемента

Я очень новичок в преобразовании XSLT. Я должен сделать преобразование сообщения FPML в более простой XML, который удалит атрибуты типа href и ID (моя целевая система не понимает этот тип сложного XML).

Таким образом, часть моего входного XML выглядит примерно так

<fpml:partyTradeInformation>
               <fpml:partyReference href="Party1"/>
               <fpml:accountReference href="Book1"/>
</fpml:partyTradeInformation>

and in same xml at bottom is the Party1 reference
   <party id="Party1">
      <fpml:partyId partyIdScheme="urn:abc:party-id:EMX-LOH">What is the partyName for PQR?</fpml:partyId>
      <fpml:partyId partyIdScheme="urn:abc:party-id:PO_ID">PO19</fpml:partyId>
      <fpml:partyId partyIdScheme="urn:abc:party-id:PO">PO19</fpml:partyId>
      <fpml:partyId partyIdScheme="urn:abc:party-id:TREATS_ID">MNO</fpml:partyId>
      <fpml:partyName>What is the partyName for PQR?</fpml:partyName>
   </party>

Now first i have to transform my party1 to like below which I am able to do
   <Party1>
      <EMX-LOH>What is the partyName for ABC?</EMX-LOH>
      <PO_ID>PO19</PO_ID><PO>PO19</PO>
      <PO>PO19</PO>
      <TREATS_ID>XYZ</TREATS_ID>
      <partyName xmlns="">What is the partyName for ABC?</partyName>
   </Party1>

But then i have to also replace my  <fpml:partyReference href="Party1"/> like 
<partyReference>
   <party>
        <Party1>
          <EMX-LOH>What is the partyName for ABC?</EMX-LOH>
          <PO_ID>PO19</PO_ID><PO>PO19</PO>
          <PO>PO19</PO>
          <TREATS_ID>XYZ</TREATS_ID>
          <partyName xmlns="">What is the partyName for ABC?</partyName>
      </Party1>
   </party>
</partyReference >

Как скопировать преобразованный набор элементов Party1 в экземпляр href? Кроме того, когда я пытаюсь выполнить сопоставление шаблона для Party1, который является преобразованным элементом XSLT, синтаксический анализатор не может его распознать. Но когда я сопоставляю партию элемента (которая является оригинальной), парсер может ее распознать.

1 ответ

Решение

Вот начало XSLT, который заменит party href соответствующим элементом party.

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

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

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="fpml:partyReference[@href]">
        <xsl:variable name="href" select="@href" />
        <partyReference>
            <party>
                <xsl:apply-templates select="//party[@id=$href]" mode="dereference" />
            </party>
        </partyReference>
    </xsl:template>

    <xsl:template match="party" />

    <xsl:template match="party" mode="dereference">
        <xsl:element name="{@id}">
            <xsl:apply-templates select="node()|@*[not(local-name()='id')]" />
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Видя, как я не знаю, что ты fpml префикс привязывается к, я вставил некоторый пример URI для этого пространства имен.

Первый шаблон соответствует node()|@* это некоторый стандартный подход, который просто скопирует все, что не соответствует другим шаблонам.

Второй шаблон соответствия fpml:partyReference[@href] возьмет любую partyReference с атрибутом href (в заданном пространстве имен), извлечет значение @href в переменную, а затем применяет шаблоны к любому элементу party, где атрибут id соответствует этому значению href. Обратите внимание, как он вводит режим с именем "разыменование". Это имя произвольно, и я выбрал кое-что.

Далее пустой шаблон, который соответствует всем party элементы и ничего не делает. Они не будут скопированы. Это позволяет избежать повторного копирования партии после того, как она уже была помещена в ссылку ранее.

Наконец, шаблон, который соответствует всем party элементы, но только в режиме dereference, Это создаст новый элемент с именем в качестве значения id Атрибут, а затем применяет шаблоны к атрибутам и дочерним узлам, за исключением атрибута id (поскольку вы не хотите, чтобы он копировался в выводе). Это будет просто по умолчанию для копирования содержимого.

Поскольку у меня недостаточно информации о том, что эти partyIdScheme Атрибуты в вашем входе делают, я не преобразовал это содержимое. Выше приведено несколько указаний о том, как решить эту проблему. Обратите внимание, что вам нужно будет изменить XSLT с правильным пространством имен для префикса fpmlи что вам может потребоваться изменить использование пространства имен, поскольку ваши выдержки XML оставляют некоторую неоднозначность относительно того, в каком именно пространстве имен находится (нам нужно увидеть правильно сформированный документ XML, чтобы понять это, а не извлекать).

Кроме того, когда я пытаюсь выполнить сопоставление шаблона для Party1, который является преобразованным элементом XSLT, синтаксический анализатор не может его распознать. Но когда я сопоставляю партию элемента (которая является оригинальной), парсер может ее распознать.

Это потому, что XSLT работает только с входным документом. Он обходит ввод, сопоставляет его части с шаблонами и выполняет инструкции в этих шаблонах. Это декларативный язык. Таким образом, генерируемый вывод не является частью ввода и не повлияет на него. Для этого вам понадобится несколько XSLT-преобразований.

Возможно, что предоставленный вами XML использует некоторые технологии, такие как XInclude или другие схемы ссылок. Вы можете получить желаемые результаты, используя парсеры, которые поддерживают правильную технологию, или некоторую библиотеку, которая реализует такие схемы ссылок, поэтому прежде чем продолжать использовать XSLT, посмотрите, есть ли что-то, что уже делает то, что вы пытаетесь.

РЕДАКТИРОВАТЬ: пример соответствия нескольких элементов в том же количестве шаблонов, что и выше. Обратите внимание, что это будет работать только если id Атрибут во входном XML уникален для каждого элемента, на который может ссылаться href, В противном случае результаты могут быть неверными.

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

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

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="fpml:partyReference[@href]|fpml:accountReference[@href]|fpml:payerPartyReference[@href]">
        <xsl:variable name="href" select="@href" />
        <xsl:element name="{local-name()}" namespace="{namespace-uri()}">
            <xsl:apply-templates select="//*[@id=$href]" mode="dereference" />
        </xsl:element>
    </xsl:template>

    <xsl:template match="party|account|payerParty" />

    <xsl:template match="party|account|payerParty" mode="dereference">
        <xsl:element name="{local-name()}" namespace="{namespace-uri()}">
            <xsl:element name="{@id}">
                <xsl:apply-templates select="node()|@*[not(local-name()='id')]" />
            </xsl:element>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>
Другие вопросы по тегам