xml - XSLT 从多个模板匹配写入相同的属性

标签 xml xslt xslt-2.0 dita

我有使用许多自定义属性的 XML,但是当往返到标准输出(本例中为 DITA)时,我需要将多个自定义属性中的值推送到同一个输出属性中。这些值可能来自与元素本身或其祖先之一匹配的模板。

这是一个简化的示例:

<concept>
    <title>Test concept</test>
    <conbody>
        <p>Info valid for everything and everyone</p>
        <p brand="product1">Some product-specific info here</p>
        <p brand="product2" country="NL">Even more specific info</p>
        <p country="NL">And this is merely localised stuff</p>
    </conbody>
</concept>

我的转换结果应该是有效的 DITA,如下所示:

<concept>
    <title>Test concept</test>
    <conbody>
        <p>Info valid for everything and everyone</p>
        <p props="brand(product1)">Some product-specific info here</p>
        <p props="brand(product2) country(NL)">Even more specific info</p>
        <p props="country(NL)">And this is merely localised stuff</p>
    </conbody>
</concept>

当我尝试从各种模板匹配写入相同的属性(每个模板匹配任何节点上的一个属性)时,输出中只出现一个值。我可以重新设计模板以使用两次传递,但在某些情况下我需要三次甚至更多,这使得它非常复杂。创建更具体的模板,当存在一个、两个或多个需要快速组合成一个的属性时触发,这会变成一个巨大的模板列表。

最简单的方法是向另一个模板创建的属性添加一个值,但我不确定这是否可以在 XSLT 2.0 中完成 - 因为一个转换的结果不可用于另一个转换。我还不够专业,还不知道是否存在任何可以帮助我创建可维护的 XSL 的东西。如果没有这样的选项,我想我最终将不得不创建一个相当复杂的多遍模板。

感谢您的肯定回答(“是的,您可以做到这一点,具体方法如下”)或否定回答(“不,这在 XSL 2.0 中无法完成”)。

最佳答案

是的,这是可能的,请参阅下面的可能解决方案:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="*[@brand or @country]">
        <xsl:copy>
            <xsl:variable name="props.value">
                <!-- Complete the list of profiling attributes -->
                <xsl:for-each select="@brand | @ country">
                    <xsl:value-of select="name()"/><xsl:text>(</xsl:text><xsl:value-of select="."/><xsl:text>)</xsl:text><xsl:text> </xsl:text>
                </xsl:for-each>
            </xsl:variable>
            <xsl:attribute name="props" select="normalize-space($props.value)"></xsl:attribute>
            <!-- TODO : process non-profiling attributes here... -->
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:transform>

在这里查看它的工作情况:http://xsltransform.net/bnnZWJ


旁注:我的答案与 @kjhughes 不同,因为我只选择和处理与 DITA 分析相关的属性 - 您不需要向 添加 id 或其他内容props 属性。

关于xml - XSLT 从多个模板匹配写入相同的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35578609/

相关文章:

android - 如何在 Android 中制作全屏 DrawerLayout?

android - Android 上的 XmlPullParser XML

xml - 使用 SAXON for Java 将存储在字符串中的 XML 片段解析为 XSLT 中的节点

.net - xslt 调试将所有值显示为 null

xml - 在同一 xpath 上进行多个测试时合并 XSL

xml - 对 XML 进行递归排序 - 仅对内部节点进行排序

java - 如何在<?xml版本="1.0"编码="UTF-8"?>之后强制java xml dom生成换行符?

xml - 寻找 Excel 的 .xlsx XML 格式的清晰描述

XSLT 2.0 Xpath 错误 "not a node item"

xml - 将 <span> 标签添加到自定义自闭合标签之间的所有文本节点