2017-02-13 85 views
-1

我对XSLT转换很陌生。 (我的目标系统不理解这种复杂的XML)XSLT转换通过复制另一个元素来替换href元素的一部分

因此,我的输入的一部分XML(我的目标系统不理解这种类型的复杂的XML)我不得不将一个FPML消息转换为更简单的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转换元素做模板匹配时,解析器无法识别它。但是,当我匹配元素派对(这是原始派对)时,解析器能够识别它。

+0

你的问题不清楚。请发布[mcve],包括XML,当前的XSLT和期望的输出。 - 我想你想学习如何使用[key](https://www.w3.org/TR/xslt/#key)。 –

回答

0

这是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的值提取到变量,然后将模板应用于id属性与href值匹配的任何聚会元素。注意它是如何引入一个名为“取消引用”的模式。这个名字是任意的,也是我选择的。

接下来是一个空模板,它匹配所有party元素并且什么也不做。他们不会被复制。这样可以避免先前已将其放置在参考中之后再次复制该方。

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

由于我没有足够的信息了解您的输入中的那些partyIdScheme属性的功能,所以我没有对这些内容进行转换。上面应该给你一些如何解决这个问题的迹象。请注意,您需要使用正确的命名空间来更改前缀为fpml的XSLT,并且您可能需要更改命名空间的使用情况,因为您的XML提取对于哪些命名空间(我们需要看到格式良好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> 
+0

完美!非常感谢。这就是我一直在寻找的东西。目标xml中不需要命名空间。所以想从输入本身中删除。 – rashb

+0

@rashb如果这足以解决问题,请考虑通过单击分数下的勾号来接受答案。这表明您认为这是帮助其他用户并提供某种声誉的正确答案。如果稍后发布更好的答案,您仍然可以更改您接受的答案。 –

+0

@rashb是的,这是绝对可能的。唯一棘手的部分是要知道应该在部件''中放置什么。它必须是正确的元素,而不是只有“聚会”。但是,如果href属性保证是唯一的,即使在不同的类型中,你也可以使用这个:' '并使用解引用模式调整模板。那可以使用像'party | account | payerParty ...'这样的东西来确保只有那些被考虑,或者通配符。 –

相关问题