I want to match a root Element “FOO” and perform the transformation (add a version attribute) to it leaving the rest as it is. The Transformation I have so far looks like this:
我想匹配一个根元素“FOO”并执行转换(添加一个版本属性)给它,剩下的就是原样。到目前为止我的转型看起来像这样:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://schemas.foo.com/fooNameSpace">
<xsl:template match="//FOO">
<xsl:choose>
<xsl:when test="@version">
<xsl:apply-templates select="node()|@*" />
</xsl:when>
<xsl:otherwise>
<FOO>
<xsl:attribute name="version">1</xsl:attribute>
<xsl:apply-templates select="node()|@*" />
</FOO>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
However this does not perform any transformation. It doesn't even detect the element. So I need to do add the namespace in order to make it work:
但是,这不会执行任何转换。它甚至没有检测到元素。所以我需要添加命名空间以使其工作:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fd="http://schemas.foo.com/fooNameSpace">
<xsl:template match="//fd:FOO">
…
But this attaches a namespace attribute to the FOO element as well as other elements:
但是这会将一个名称空间属性附加到FOO元素以及其他元素:
<FOO xmlns:fd="http://schemas.foo.com/fooNameSpace" version="1" id="fooid">
<BAR xmlns="http://schemas.foo.com/fooNameSpace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- Is there a way to say that the element is using the default namespace?
- 有没有办法说该元素使用默认命名空间?
- Can we match and add elements in the default name space?
- 我们可以在默认名称空间中匹配和添加元素吗?
Here is the original XML:
这是原始的XML:
<?xml version="1.0" encoding="UTF-8"?>
<FOO xmlns="http://schemas.foo.com/fooNameSpace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<BAR>
<Attribute name="HEIGHT">2067</Attribute>
</BAR>
</FOO>
3 个解决方案
#1
1
You can specify the default namespace for XPath expressions by adding the attribute xpath-default-namespace
, as described in the section 5.2 Unprefixed QNames in Expressions and Patterns of the XSLT 2.0 standard.
您可以通过添加属性xpath-default-namespace来为XPath表达式指定默认命名空间,如第5.2节XSLT 2.0标准的表达式和模式中的未加固定的QName中所述。
Example:
例:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://schemas.foo.com/fooNameSpace">
<xsl:template match="FOO[not(@version)]">
<xsl:copy>
<xsl:attribute name="version">1</xsl:attribute>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- Identity template for copying everything else -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
#2
0
This works for me using xsltproc/libxslt:
这适用于我使用xsltproc / libxslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://schemas.foo.com/fooNameSpace">
<xsl:template match="/ns:FOO">
<xsl:copy>
<xsl:if test="not(@version)">
<xsl:attribute name="version">1</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
It produces:
它产生:
<?xml version="1.0"?>
<FOO xmlns="http://schemas.foo.com/fooNameSpace" version="1">
<BAR>
<Attribute>2067</Attribute>
</BAR>
</FOO>
#3
0
Here is one solution truly in the spirit of XSLT:
这是一个真正符合XSLT精神的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fd="http://schemas.foo.com/fooNameSpace"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[self::fd:FOO and not(@version)]">
<xsl:copy>
<xsl:attribute name="version">1</xsl:attribute>
<xsl:call-template name="identity"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document, the wanted, correct result is produced:
在提供的XML文档上应用此转换时,将生成所需的正确结果:
<FOO xmlns="http://schemas.foo.com/fooNameSpace"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1">
<FOO>
<BAR>
<Attribute name="HEIGHT">2067</Attribute>
</BAR>
</FOO>
</FOO>
#1
1
You can specify the default namespace for XPath expressions by adding the attribute xpath-default-namespace
, as described in the section 5.2 Unprefixed QNames in Expressions and Patterns of the XSLT 2.0 standard.
您可以通过添加属性xpath-default-namespace来为XPath表达式指定默认命名空间,如第5.2节XSLT 2.0标准的表达式和模式中的未加固定的QName中所述。
Example:
例:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://schemas.foo.com/fooNameSpace">
<xsl:template match="FOO[not(@version)]">
<xsl:copy>
<xsl:attribute name="version">1</xsl:attribute>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- Identity template for copying everything else -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
#2
0
This works for me using xsltproc/libxslt:
这适用于我使用xsltproc / libxslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://schemas.foo.com/fooNameSpace">
<xsl:template match="/ns:FOO">
<xsl:copy>
<xsl:if test="not(@version)">
<xsl:attribute name="version">1</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
It produces:
它产生:
<?xml version="1.0"?>
<FOO xmlns="http://schemas.foo.com/fooNameSpace" version="1">
<BAR>
<Attribute>2067</Attribute>
</BAR>
</FOO>
#3
0
Here is one solution truly in the spirit of XSLT:
这是一个真正符合XSLT精神的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fd="http://schemas.foo.com/fooNameSpace"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*[self::fd:FOO and not(@version)]">
<xsl:copy>
<xsl:attribute name="version">1</xsl:attribute>
<xsl:call-template name="identity"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document, the wanted, correct result is produced:
在提供的XML文档上应用此转换时,将生成所需的正确结果:
<FOO xmlns="http://schemas.foo.com/fooNameSpace"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1">
<FOO>
<BAR>
<Attribute name="HEIGHT">2067</Attribute>
</BAR>
</FOO>
</FOO>