我有使用许多自定义属性的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。如果没有这样的选项,我想我将不得不创建一个相当复杂的多遍模板。
感谢您的肯定答案(&#34;是的,您可以这样做,这里是如何&#34;)或者是否定的答案(&#34;不,这不能在XSL 2.0和#34中完成; )。
答案 0 :(得分:3)
是的,有可能,请参阅下面的可能解决方案:
<?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
或其他任何内容} attributes。
答案 1 :(得分:2)
调整心智模型,使其远离从多个模板写入单个属性值。相反,请考虑您希望属性值是什么以及如何从XSLT中的单个位置 中输入XML 的部分收集属性值的各个部分
您的大部分输出应与输入相同,因此请从身份转换开始。然后为p
编写一个特殊案例模板,您可以通过迭代输入@props
元素的属性来创建其特殊的p
属性。
以下是基础知识......
根据您的XML输入,
<concept>
<title>Test concept</title>
<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>
此XSLT 1.0(或2.0)转换,
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p[@*]">
<xsl:copy>
<xsl:attribute name="props">
<xsl:for-each select="@*">
<xsl:value-of select="name()"/>
<xsl:text>(</xsl:text>
<xsl:value-of select="."/>
<xsl:text>)</xsl:text>
<xsl:if test="position() != last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
将产生此XML输出
<?xml version="1.0" encoding="UTF-8"?>
<concept>
<title>Test concept</title>
<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>
根据要求。