【发布时间】:2025-12-08 04:15:01
【问题描述】:
我需要为几个具有不同命名空间的“嵌入”文档的输入文档翻译 XML->XML。这些嵌入文档具有相同类型的元素(即基于相同的 xsd),我想以通用方式/模板将其映射到输出文档中 - 无论命名空间如何。
简单示例输入 XML:
<?xml version="1.0" encoding="UTF-8"?>
<Message xmnls="mymessage">
<Header>...</Header>
<Body xmlns="type1">
<DocumentType1>
<Creditor>
<Name>Mr Creditor</Name>
<Address>Muddy Creek 42</Address>
</Creditor>
<CreditorAccount>
<Id>794115296</Id>
</CreditorAccount>
</DocumentType1>
</Body>
</Message>
示例输入 XML 2:
<?xml version="1.0" encoding="UTF-8"?>
<Message xmnls="mymessage">
<Header>...</Header>
<Body xmlns="type2"><!-- different namespace -->
<DocumentType2>
<Creditor><!-- same element -->
<Name>Mr Creditor</Name>
<Address>Muddy Creek 42</Address>
</Creditor>
<CreditorAccount>
<Id>794115296</Id>
</CreditorAccount>
</DocumentType2>
</Body>
</Message>
对于这两个示例,我想提取结构相同的“贷方”信息。 但正如您所见,Body-namespace ("type1", "type2"...) 和 child-Element name ("DocumentType1",...) 各不相同,即整个名称,而不仅仅是末尾的数字。
两种情况下的输出应该是这样的:
<?xml version="1.0"?>
<Request>
<Creditor>
<Name>Mr Creditor</Name>
<Address>Muddy Creek 42</Address>
<Account>794115296</Account>
</Creditor>
</Request>
如何使用 XSLT 1.0 / libxml+exslt 以最佳方式以输出格式映射两个消息示例的贷方信息?遗憾的是我绑定到 1.0。
我当然可以使用“通配符”,但我担心这可能会降低性能。 XSLT 中会有很多这样的映射,并且输入数据比示例更多。您在性能方面有经验吗?
否则我需要为每个不同的命名空间创建一个模板,对吗?据我了解,没有办法在 XSLT 中为命名空间动态设置别名。
这是一个使用“通配符”的 XSLT 示例:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:mymessage="urn:mymessage"
exclude-result-prefixes="xsi xsl mymessage"
version="1.0">
<xsl:template match="//mymessage:Message">
<Request>
<xsl:apply-templates/>
</Request>
</xsl:template>
<xsl:template match="mymessage:Header"/>
<xsl:template match="*[local-name()='Body']">
<Creditor>
<Name>
<xsl:value-of select="*/*[local-name()='Creditor']/*[local-name()='Name']"/>
</Name>
<Address>
<xsl:value-of select="*/*[local-name()='Creditor']/*[local-name()='Address']"/>
</Address>
<Account>
<xsl:value-of select="*/*[local-name()='CreditorAccount']/*[local-name()='Id']"/>
</Account>
</Creditor>
</xsl:template>
</xsl:stylesheet>
感谢您的帮助! :)
【问题讨论】:
-
您是否有
Body及其后代可能位于的所有可能命名空间的列表? -
@michael.hor257k:命名空间实际上是 ISO20022 消息类型,例如“pacs.008.001.08”、“pacs.004.001.09”、“camt.053.001.08”等。我将从一组比如说 5 种消息类型开始,但以后可能会增加。所以是的,我有一个完整的列表,但就未来的改编而言,它并不详尽。
-
@BusyBeaver 有人在那里做了一个非常糟糕的设计决定。我敢肯定他们认为这很聪明,但他们显然从未做过任何认真的 XML 编程。
-
@MichaelKay 我同意... imo 这个“标准”被每个组使用它自己的一组消息和自己的版本分成几部分(版本是命名空间的一部分,如 *. 08, *.09 ...) 并引入细微的变化以满足他们的要求。构建财务信息的意图是好的,但最终它隐藏在一堆“方言”中,导致语言混乱。 ;)