XSLT转换通过复制另一个元素来替换href元素的发生

时间:2017-02-13 12:24:55

标签: xslt href fpml

我对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元素集? 此外,当我尝试为Party1(XSLT转换元素)进行模板匹配时,解析器无法识别它。但是当我匹配元素方(原始元素方)时,解析器能够识别它。

1 个答案:

答案 0 :(得分:0)

这是XSLT的开始,它将使用相应的派对元素替换派对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的值提取到变量,然后将模板应用于id属性匹配的任何party元素那个href值。请注意它是如何引入一个名为&#34; dereference&#34;的模式。这个名字是任意的,我选择了。

接下来是一个匹配所有party元素的空模板,不执行任何操作。他们不会被复制。这样可以避免在早先将参与者放入参考之后再次复制该参与者。

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

由于我没有足够的信息来了解输入中partyIdScheme个属性的内容,因此我无法转换这些内容。以上应该给你一些如何解决这个问题的迹象。请注意,您需要使用前缀fpml的正确名称空间来更改XSLT,并且您可能需要更改名称空间使用情况,因为您的XML提取会对哪个名称空间中的内容留下一些含糊之处(我们&#39; d需要看到结构良好的XML文档才能弄清楚而不是提取出来。)

  

此外,当我尝试为Party1(XSLT转换元素)进行模板匹配时,解析器无法识别它。但是当我匹配元素方(原始元素方)时,解析器能够识别它。

这是因为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>