Я хотел бы скопировать этот XML
структура в другую с некоторыми
исключение [...]
Мои правила:
1) Копировать все корневые атрибуты, кроме
foo3
2) Скопируйте все дочерние узлы (), если только
названные foo1 и foo2
Обновление от комментариев :
Привет, это почти работа. Кроме этого
data / foo1 должен быть скопирован
Эта таблица стилей:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/@foo3|root/foo1|foo2"/>
</xsl:stylesheet>
Выход:
<root foo1="bar1" foo2="bar2">
<data>
<foo1>bar1</foo1>
<foo3>bar3</foo3>
</data>
</root>
Примечание : перезапись правила идентификации пустыми шаблонами
С именами узлов в параметре, эта таблица стилей:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="pStrip" select="'root/@foo3|root/foo1|foo2'"/>
<xsl:template match="node()|@*" name="identity">
<xsl:param name="pStripPaths" select="concat($pStrip,'|')"/>
<xsl:param name="pNodePath">
<xsl:call-template name="path"/>
<xsl:text>|</xsl:text>
</xsl:param>
<xsl:variable name="vStripPath"
select="substring-before($pStripPaths,'|')"/>
<xsl:choose>
<xsl:when test="not($pStripPaths)">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:when>
<xsl:when test="contains($pNodePath,concat('/',$vStripPath,'|'))"/>
<xsl:otherwise>
<xsl:call-template name="identity">
<xsl:with-param name="pStripPaths"
select="substring-after($pStripPaths,'|')"/>
<xsl:with-param name="pNodePath" select="$pNodePath"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()" name="path" mode="path">
<xsl:apply-templates select="parent::*" mode="path"/>
<xsl:value-of select="concat('/',
substring('@',
1 div (count(.|../@*)
= count(../@*))),
name())"/>
</xsl:template>
</xsl:stylesheet>
Выход:
<root foo1="bar1" foo2="bar2">
<data>
<foo1>bar1</foo1>
<foo3>bar3</foo3>
</data>
</root>
Примечание : В XML имя элемента относится к схеме, в основном определяющей положение иерархии, но ваше дело не в этом.
Редактировать : просто для удовольствия, решение XSLT 2.0:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:local="http://localhost">
<xsl:param name="pStrip" select="'root/@foo3|root/foo1|foo2'"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[local:match($pStrip,.)]|@*[local:match($pStrip,.)]"/>
<xsl:function name="local:match" as="xs:boolean">
<xsl:param name="pStripPaths" as="xs:string"/>
<xsl:param name="pNode" as="item()"/>
<xsl:variable name="vNodePath"
select="string-join(($pNode
/ancestor::node()
/name(),
if ($pNode instance of attribute())
then concat('@',name($pNode))
else name($pNode)),
'/')"/>
<xsl:sequence select="some $path in tokenize($pStripPaths,'\|')
satisfies ends-with($vNodePath,
concat('/',$path))"/>
</xsl:function>
</xsl:stylesheet>
Редактировать 2 : Все таблицы стилей следуют одному и тому же строковому шаблону.