我想在xml结构中将xml属性提升一级。 至于要求我展示了一个更详细的例子:
<items>
<kitchen>
<furnitures>
<chairs type="wood">
<chair_1 color="green" legs="4"/>
</chairs>
<tables type="stone">
</tables>
</furnitures>
</kitchen>
</items>
我想输出这个:
<items>
<kitchen>
<furnitures>
<chairs type="wood"/>
<chair_1 color="green" legs="4"/>
<tables type="stone">
</tables>
</furnitures>
</kitchen>
</items>
如您所见,我将char_1移到
下面<xsl:template match="node()">
<xls:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="*"/>
<xsl:apply-templates select="text()">
</xsl:copy>
</xsl:template>
<xsl:template match="/items/kitchen/furnitures/chairs">
<xsl:choose>
<xsl:when test="chair_1">
<xsl:copy>
<xsl:apply-templates select="child::node()[not(self:chair_1)]|@*|text()"/>
</xsl:copy>
<xsl:apply-templates select="chair_1"/>
</xsl:when>
<!----- edit -->
<xsl:otherwise>
<xsl:copy>
<xls:apply-templates select ="@*|node()"/>
</xsl:copy>
<xsl:apply-templates select="settings"/>
<xsl:text>
</xsl:text>
<chair_1 color="green" legs="4"/>
</xls:otherwise>
</xls:choose>
</xsl:template>
所以,我的主要问题是,我的副本不包含换行符。 请记住,我正在使用PHP:Xsltproc,在我的dev-comp上缩进工作正常,但是使用PHP的xsltproc它不好,并删除换行符。 所以输出如下:
<items>
<kitchen>
<furnitures>
<chairs type="wood"/><chair_1 color="green" legs="4"/>
<tables type="stone">
</tables>
</furnitures>
</kitchen>
</items>
哪个好,但没有正确缩进。 (免责声明:可能有一些拼写错误,因为这不是原始的XML,当然我使用所需的样式表,版本,phpversion,xml版本标签,当然我的输出方法是xml和indent =“是”)
更新: 当我有第二个“WHEN”时,(如果没有chair_1)我想把它“粘贴”到代码中。但缩进失败,它使整个副本成一行。可能是什么问题?
答案 0 :(得分:1)
您提供的模板不会影响您所说的转换,至少不会影响它们自己。实际上,它们甚至都不是有效的XSL。
在纠正明显的语法错误之后,匹配node()
的结果模板显式重新排列元素周围的空白(不剥离),并且在保留属性方面没有任何效果。你似乎打算将它作为一个身份变换,但传统的身份变换是这样的:
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
特别注意node()
测试匹配元素和文本节点(以及注释和处理指令),但不匹配属性,并且如果您不想重新排列元素的文本节点相对对于它的子元素,那么你必须通过相同的xsl:apply-templates
指令将它们全部转换。
此外,请注意,在许多XML应用程序中,仅用空白的文本分隔标记运行是无关紧要的。我没有理由认为您的特定应用程序属于例外情况,所以您真的应该问自己是否重要?#34;
假设它确实重要 - 例如因为你想要提高人类的可读性,即使XML主要是由不关心缩进的计算机程序使用 - 你应该考虑让你的XSL处理器为你提供缩进。为此,首先从输入文档中剥离所有无关紧要的空格开始:
<xsl:strip-space elements="*"/>
并通过要求处理器为您提供分层缩进来跟进:
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
这两个指令都具有全局效果,它们需要显示为xsl:stylesheet
或xsl:transform
元素的直接子元素。这是已清理和更新的版本:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/items/kitchen/furnitures/chairs">
<xsl:choose>
<xsl:when test="chair_1">
<xsl:copy>
<!-- also simplified the 'select' expression below: -->
<xsl:apply-templates select="node()[not(self::chair_1)]|@*"/>
</xsl:copy>
<xsl:apply-templates select="chair_1"/>
</xsl:when>
<xsl:otherwise>
BUNCH of code there if we don't have chair_1
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>