XSLT 转换通过复制另一个元素替换 href 元素的出现

XSLT transformation replacing occurenece of href elements by copying another element

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

如何在 href 实例中复制转换后的 Party1 元素集? 此外,当我尝试为 XSLT 转换元素 Party1 进行模板匹配时,解析器无法识别它。但是当我匹配元素派对(这是原始的)时,解析器能够识别它。

这是 XSLT 的开始,它将用相应的 party 元素替换 party 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]">
        <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] 的第二个模板将采用任何具有 href 属性的 partyReference(在给定的命名空间中),将 @href 的值提取到一个变量,然后将模板应用于任何 party 元素,其中 id属性匹配该 href 值。请注意它是如何引入名为 "dereference" 的模式的。这个名字是任意的,是我选择的。

Next 是一个空模板,它匹配所有 party 元素并且不执行任何操作。他们不会被复制。这避免了在先前已将其放入参考中后再次复制该方。

最后是一个匹配所有 party 元素的模板,但仅当处于 dereference 模式时。这将创建一个新元素,其名称为 id 属性的值,然后将模板应用于属性和子节点,但 id 属性除外(因为您不希望在输出中复制它) .这将默认为复制内容。

由于我没有足够的信息来了解您输入的 partyIdScheme 属性的作用,因此我没有转换这些内容。上面应该给你一些关于如何解决这个问题的指示。请注意,您将需要使用前缀 fpml 的正确命名空间更改 XSLT,并且您可能需要更改命名空间的使用,因为您的 XML 提取对于哪个命名空间中的内容存在一些歧义(我们需要查看 well-formed XML 文档来弄清楚而不是摘录)。

Also when i try to do a template match for Party1 which is the XSLT transformed element, the parser is not able to recognize it. But when i match the element party (which is the original one) the parser is able to recognize it.

那是因为 XSLT 仅适用于输入文档。它遍历输入,将其部分与模板匹配并执行这些模板中的指令。它是一种声明性语言。所以生成的输出不是输入的一部分,不会影响它。为此,您需要多个 XSLT 转换。

向您提供的 XML 可能使用了一些技术,例如 XInclude 或其他引用方案。您可能能够使用支持正确技术的解析器或实现此类引用方案的某些库来获得所需的结果,因此在您继续使用 XSLT 之前,请查看是否已经有一些东西可以满足您的要求。

编辑:在与上述相同数量的模板中匹配多个元素的示例。请注意,只有当输入 XML 中的 id 属性对于可以被 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>