从XPath表达式填充XML模板文件?

从XPath表达式的映射中填充(或生成)XML模板文件的最佳方法是什么?

要求是我们需要从模板开始(因为这可能包含未在XPath表达式中捕获的信息)。

例如,起始模板可能是:

  
?XXX? ?XXX? ?999.99? ??? ???

然后我们提供,例如:

 expression: /create/article[1]/id => 1 expression: /create/article[1]/description => bar expression: /create/article[1]/name[1] => foo expression: /create/article[1]/price[1]/amount => 00.00 expression: /create/article[1]/price[1]/currency => USD expression: /create/article[2]/id => 2 expression: /create/article[2]/description => some name expression: /create/article[2]/name[1] => some description expression: /create/article[2]/price[1]/amount => 00.01 expression: /create/article[2]/price[1]/currency => USD 

然后我们应该生成:

  
foo bar 00.00 USD 1
some name some description 00.01 USD 2

我是用Java实现的,虽然如果可能的话,我更喜欢基于XSLT的解决方案。

PS:这个问题与我最近提出的另一个问题相反。

此转换从“表达式”创建一个具有所需结果结构的XML文档 – 它仍然可以将此结果转换为最终结果

    1 bar foo 00.00 USD 11.11 AUD 2 some name some description 00.01 USD                       

当此转换应用于任何XML文档(未使用)时,结果为

  
1 bar foo 00.00 USD 11.11 AUD
2 some name some description 00.01 USD

注意

  1. 您需要将您给出的“表达式”转换为此转换中使用的格式 – 这很简单直接。

  2. 在最终转换中,您需要“按原样”复制每个节点(使用标识规则),但顶级节点应在"http://predic8.com/wsdl/material/ArticleService/1/"生成。 "http://predic8.com/wsdl/material/ArticleService/1/"命名空间。 请注意,“模板”中存在的其他命名空间未使用,可以安全地省略。

此解决方案要求您稍微重新组织XPATH输入信息,并允许两步转换。 第一个转换将编写样式表,它将在第二个转换中执行 – 因此客户端需要对XSLT引擎进行两次调用。 如果这是一个问题,请告诉我们。

第一步

请将您的XPATH信息重新组织到XML文档中。 这应该不难,甚至可以编写XSLT脚本来完成这项工作。

   article[1]/id[1]  http://predic8.com/wsdl/material/ArticleService/1/   1   article[1]/description[1]  bar  ... etc ...  

解决方案限制

在上面的规则文件中,我们受到限制,以便:

  1. 该匹配隐式加上前缀’expression:/ create /’。 不要明确地说明。
  2. 所有匹配必须以article [n]开头,其中n是某个序数。
  3. 我们不能有零规则。
  4. 您在匹配中使用的任何前缀,除了s11 =“http://schemas.xmlsoap.org/soap/envelope/”和ns1 =“http://predic8.com/wsdl/material/ArticleService/1/” 。 (注意:我不认为命名空间以’/’结尾有效 – 但不确定),在命名空间节点中定义。

以上是第一步转换的输入文档。 将此文档应用于此样式表…

                                                 

第二步

将肥皂信封文件作为输入文档应用于从第一步输出的样式表。 结果是原始的soap文档,根据需要进行了更改。 这是第二步样式表的示例,为了简化说明,仅考虑第一个规则(/ create / article [1] / id => 1)。

                 

更多解决方案限制

  1. 模板文档必须至少包含一个/ s11:Envelope / s11:Body / ns1:create / article。 根据规则的要求,只复制文章节点(深度)。 除了它可以是任何结构。
  2. 模板文档不能包含s11:Envelope / s11:Body / ns1:create节点的嵌套级别。

说明

您会注意到XPATH表达式与模板的匹配条件相差不远。 因此,编写一个将XPATH和替换值重新表示为模板规则的样式表并不困难。 在编写样式表编写样式表时,xsl:namespace-alias使我们能够将“xsl: ”作为指令消除歧义, 并将“xsl: ”作为预期输出消除歧义。 当XSLT 3.0出现时,我们很可能能够将此算法简化为一步,因为它将允许动态XPATH评估,这实际上是您问题的核心。 但目前我们必须满足于两个步骤。

第二个样式表是两阶段转换。 第一阶段从文章级别复制模板,根据规则的需要多次复制。 第二阶段解析此复制模板,并应用动态规则替换XPATH指示的文本值。


UPDATE

我原来的post错了。 感谢Dimitre指出错误。 请在上面找到更新的解决方

经过深思熟虑

如果两步解决过于复杂,并且您在wintel平台上运行,您可以考虑购买Saxon的商业版本。 我相信商业版具有动态XPATH评估function。 我不能给你这样的解决方案,因为我没有商业版本。 我想使用evaluate()函数的解决方案会简单得多。 XSLT对我来说只是一个爱好。 但是,如果您将XSLT用于商业目的,价格是合理的。