简体   繁体   English

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

[英]XSLT transformation replacing occurenece of href elements by copying another element

I'm very new to XSLT transformation.我对 XSLT 转换很陌生。 I have to do a transformation of an FPML message into a simpler XML which will remove the href's and ID kind of attributes.(My target system doesn't understand this type of complex XML)我必须将 FPML 消息转换为更简单的 XML,这将删除 href 和 ID 类型的属性。(我的目标系统不理解这种类型的复杂 XML)

So part of my input XML is something like this所以我的输入 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 >

How do i copy the transformed Party1 set of element at the href instance?如何在 href 实例中复制已转换的 Party1 元素集? 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.此外,当我尝试为 Party1 进行模板匹配时,它是 XSLT 转换的元素,解析器无法识别它。 But when i match the element party (which is the original one) the parser is able to recognize it.但是当我匹配元素方(这是原始方)时,解析器能够识别它。

Here's a start for an XSLT that will replace the party href with the corresponding party element.这是一个 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>

Seeing how I don't know what your fpml prefix binds to, I put in some sample URI for that namespace.看到我不知道您的fpml前缀绑定到什么,我为该命名空间放入了一些示例 URI。

The first template matching node()|@* is some standard approach that will just copy anything that doesn't match any other templates.第一个模板匹配node()|@*是一些标准方法,它只会复制与任何其他模板不匹配的任何内容。

The second template matching fpml:partyReference[@href] will take any partyReference with a href attribute (in the given namespace), extract the value of @href to a variable, and then applies templates to any party element where the id attribute matches that href value.匹配fpml:partyReference[@href]的第二个模板将获取任何具有 href 属性的 partyReference(在给定的命名空间中),将@href 的值提取到一个变量,然后将模板应用于 id 属性匹配的任何 party 元素href 值。 Notice how it introduces a mode named "dereference".请注意它如何引入名为“取消引用”的模式。 That name is arbitrary and something I chose.这个名字是任意的,是我选择的。

Next is an empty template that matches all party elements and does nothing.接下来是一个空模板,它匹配所有party元素并且什么都不做。 They won't get copied.他们不会被复制。 This avoids copying the party again after it had already been placed in the reference earlier.这避免了在早先已经放置在参考中之后再次复制该方。

Finally is a template that matches all party elements, but only when in mode dereference .最后是一个匹配所有party元素的模板,但仅限于模式dereference This will create a new element with as name the value of the id attribute and then applies templates to the attributes and child nodes, with the exception of the id attribute (since you don't want it copied in the output).这将创建一个名为id属性值的新元素,然后将模板应用于属性和子节点,但 id 属性除外(因为您不想在输出中复制它)。 This will just default to copying the contents.这将默认为复制内容。

Since I don't have enough information about what those partyIdScheme attributes in your input do, I haven't transformed those contents.由于我没有足够的关于您输入中的那些partyIdScheme属性的信息,因此我没有转换这些内容。 The above should give you some indications of how to solve this.以上应该给你一些如何解决这个问题的迹象。 Note that you will need to alter the XSLT with the right namespace for prefix fpml , and that you may need to alter the namespace usage since your XML extracts leave some ambiguity about what is in which namespace (we'd need to see well-formed XML document to figure that out rather than extracts).请注意,您需要使用前缀fpml的正确名称空间更改 XSLT,并且您可能需要更改名称空间的使用,因为您的 XML 提取对哪个名称空间中的内容存在一些歧义(我们需要看到格式良好的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.此外,当我尝试为 Party1 进行模板匹配时,它是 XSLT 转换的元素,解析器无法识别它。 But when i match the element party (which is the original one) the parser is able to recognize it.但是当我匹配元素方(这是原始方)时,解析器能够识别它。

That is because XSLT only works on the input document.这是因为 XSLT 仅适用于输入文档。 It traverses the input, matches its parts to templates and executes the instructions in those templates.它遍历输入,将其部分与模板匹配并执行这些模板中的指令。 It's a declarative language.它是一种声明性语言。 So the output being generated is not part of the input and won't affect it.所以生成的输出不是输入的一部分,不会影响它。 You'd need multiple XSLT transformations for that.为此,您需要多个 XSLT 转换。

It's possible that the XML you're provided makes use of some technologies such as XInclude or other referencing schemes.您提供的 XML 可能使用了一些技术,例如 XInclude 或其他引用方案。 You may be able to get your desired results using parsers that support the right technology or some library that implements such referencing schemes, so before you continue using XSLT, see if there's something that already does what you're trying.您可能能够使用支持正确技术的解析器或实现此类引用方案的某些库来获得所需的结果,因此在您继续使用 XSLT 之前,请查看是否有某些东西已经在执行您正在尝试的操作。

EDIT: an example matching multiple elements in the same amount of templates as above.编辑:与上述相同数量的模板中的多个元素匹配的示例。 Note that this will only work if the id attribute in the input XML is unique for every element that can get referenced by href .请注意,这仅在输入 XML 中的id属性对于可以被href引用的每个元素都是唯一的时才有效。 Otherwise the results might be incorrect.否则结果可能不正确。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM