如何避免在 XSLT 中生成空属性?

发布于 2024-11-02 19:53:54 字数 692 浏览 1 评论 0原文

我已经使用以下代码编写了 XSLT 文件:

<xsl:attribute name="subCode">
    <xsl:value-of select="Field[@key='XY']"/>
</xsl:attribute>

假设我的 INPUT XML 如下所示:

[...]
<Field key="XY"/>
[...]

在这种情况下,我的 XSLT 将生成以下输出:

<SomeElement subCode="">
[...]
</SomeElement>

我的问题是: 如何摆脱空属性 subCode=""< /代码>?

我知道可以通过使用像 这样的条件指令来实现,但是,这似乎是一个丑陋的解决方案(因为我在 XSLT 中生成了数千个类似的属性)。

它必须在同一个 XSLT 中完成。我无法在其他 XSLT 文件中添加后处理。

除此之外,输出 XML 已定义其 XSD 架构。架构表明此属性是可选。也许有某种方法可以将该 XSD 架构应用于输出 XML?

预先感谢您的任何帮助!

I have written XSLT file with the following code:

<xsl:attribute name="subCode">
    <xsl:value-of select="Field[@key='XY']"/>
</xsl:attribute>

Let's say that my INPUT XML looks like this:

[...]
<Field key="XY"/>
[...]

In this case my XSLT would generate the following output:

<SomeElement subCode="">
[...]
</SomeElement>

My question is: How to ged rid of empty attribute subCode=""?

I know that it is possible by using some conditional instruction like <xsl:if>, however, this seems to be an ugly solution (because I have thousands of similar attributes generated in my XSLT).

It must be done in the same XSLT. I cannot add post-processing in additional XSLT file.

Besides that, the output XML has got its XSD Schema defined. And the schema says that this attribute is optional. Maybe there is some way to apply that XSD schema for the output XML?

Thanks in advance for any help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

盛夏尉蓝 2024-11-09 19:53:54

使用

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
  <someElement>
    <xsl:apply-templates mode="attr"/>
  </someElement>
 </xsl:template>

 <xsl:template match="Field[@key='XY' and not(.='')]" mode="attr">
    <xsl:attribute name="subCode">
      <xsl:value-of select="."/>
    </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时:

<t>
 <Field key="XY"/>
</t>

生成所需的正确结果(根本不生成任何属性)

当源 XML 文档是这样的时:

<t>
 <Field key="XY">1</Field>
</t>

相同的转换再次产生正确的、想要的结果;

<someElement subCode="1"/>

Use:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
  <someElement>
    <xsl:apply-templates mode="attr"/>
  </someElement>
 </xsl:template>

 <xsl:template match="Field[@key='XY' and not(.='')]" mode="attr">
    <xsl:attribute name="subCode">
      <xsl:value-of select="."/>
    </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the following XML document:

<t>
 <Field key="XY"/>
</t>

the wanted, correct result (no attribute at all is generated) is produced:

when the source XML document is this:

<t>
 <Field key="XY">1</Field>
</t>

the same transformation again produces the correct, wanted result;

<someElement subCode="1"/>
笙痞 2024-11-09 19:53:54

您可以定义一个模板来匹配该属性,该属性将为您提供缺少的 @key 的正确输出,但如果您还添加谓词 [.!=''] 它然后还应该忽略没有值的属性。

<xsl:template match="@key[.!='']">
  <xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>

或者在您的示例中,如果您只想 @key='XY' 匹配,请使用:

<xsl:template match="@key[.='XY']">
  <xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>

编辑: 这是我用来测试此功能的更完整的示例。

源 XML

<Fields>
   <Field key="XY">A</Field>
   <Field key="XY">B</Field>
   <Field key="">C</Field>
   <Field>D</Field>
</Fields>

附带 XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="Field">
  <xsl:element name="NewField">
    <xsl:apply-templates select="@*"/>
    <xsl:value-of select="."/>
  </xsl:element>
</xsl:template>

<xsl:template match="@key[.='XY']">
  <xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
</xsl:stylesheet>

结果

<output>
  <NewField subCode="XY">A</NewField>
  <NewField subCode="XY">B</NewField>
  <NewField>C</NewField>
  <NewField>D</NewField>
</output>

You can define a template to match the attribute which will give you the correct output for a missing @key but if you also add the predicate [.!=''] it should then also ignore the attributes with no value.

<xsl:template match="@key[.!='']">
  <xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>

Or in your example if you only want the @key='XY' matches use:

<xsl:template match="@key[.='XY']">
  <xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>

Edit: Here is a more complete example that I used to test this.

Source XML

<Fields>
   <Field key="XY">A</Field>
   <Field key="XY">B</Field>
   <Field key="">C</Field>
   <Field>D</Field>
</Fields>

Accompanying XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="Field">
  <xsl:element name="NewField">
    <xsl:apply-templates select="@*"/>
    <xsl:value-of select="."/>
  </xsl:element>
</xsl:template>

<xsl:template match="@key[.='XY']">
  <xsl:attribute name="subCode"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
</xsl:stylesheet>

Result

<output>
  <NewField subCode="XY">A</NewField>
  <NewField subCode="XY">B</NewField>
  <NewField>C</NewField>
  <NewField>D</NewField>
</output>
林空鹿饮溪 2024-11-09 19:53:54

您应该将以下模板应用于您的属性:

此模板匹配所有值为 'XY' 的 key 属性:

<xsl:template match="@key['XY']">
    <xsl:attribute name="subCode">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

此模板匹配所有带有(文本)的 key 属性值长于 0:

<xsl:template match="@key[string-length(.)]">
    <xsl:attribute name="other">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

最后,此模板匹配所有为空的属性 (*):

<xsl:template match="@*[not(string-length(.))]" />

因此,如果您有类似的输入,

<?xml version="1.0"?>
<Root>
    <Field key='v'>One</Field>
    <Field key='XY'>Two</Field>
    <Field key='a'>Three</Field>
    <Field key='v'>Four</Field>
    <Field key='XY'>Five</Field>
    <Field>Six</Field>
    <Field>Seven</Field>
    <Field key='b'>Eight</Field>
    <Field key=''>Nine</Field>
    <Field></Field>
    <Field key='x'>Eleven</Field>
    <Field key=''>Twelve</Field>
    <Field lat='x'>Thirteen</Field>
</Root>

则可以生成输出:

<?xml version='1.0' ?>
<Root>
    <SomeField other="v">One</SomeField>
    <SomeField subCode="XY">Two</SomeField>
    <SomeField other="a">Three</SomeField>
    <SomeField other="v">Four</SomeField>
    <SomeField subCode="XY">Five</SomeField>
    <SomeField>Six</SomeField>
    <SomeField>Seven</SomeField>
    <SomeField other="b">Eight</SomeField>
    <SomeField>Nine</SomeField>
    <SomeField/>
    <SomeField other="x">Eleven</SomeField>
    <SomeField>Twelve</SomeField>
    <SomeField>xThirteen</SomeField>
</Root>

使用以下 xslt:

<?xml version="1.0"?>
<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="/">
        <Root>
            <xsl:apply-templates/>
        </Root>
    </xsl:template>

    <xsl:template match="Field">
        <xsl:element name="SomeField">
            <xsl:apply-templates select="@*"/>
            <xsl:value-of select="text()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@key['XY']">
        <xsl:attribute name="subCode">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@key[string-length(.)]">
        <xsl:attribute name="other">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@key[not(string-length(.))]" />
</xsl:stylesheet>

You should apply the following templates to your attributes:

This template matches all key the attributes who's value is 'XY':

<xsl:template match="@key['XY']">
    <xsl:attribute name="subCode">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

This template matches all the key attributes with a (text)value longer than 0:

<xsl:template match="@key[string-length(.)]">
    <xsl:attribute name="other">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

And finally this template matches all the attributes (*) that are empty:

<xsl:template match="@*[not(string-length(.))]" />

So if you have an input like

<?xml version="1.0"?>
<Root>
    <Field key='v'>One</Field>
    <Field key='XY'>Two</Field>
    <Field key='a'>Three</Field>
    <Field key='v'>Four</Field>
    <Field key='XY'>Five</Field>
    <Field>Six</Field>
    <Field>Seven</Field>
    <Field key='b'>Eight</Field>
    <Field key=''>Nine</Field>
    <Field></Field>
    <Field key='x'>Eleven</Field>
    <Field key=''>Twelve</Field>
    <Field lat='x'>Thirteen</Field>
</Root>

You can generate an output:

<?xml version='1.0' ?>
<Root>
    <SomeField other="v">One</SomeField>
    <SomeField subCode="XY">Two</SomeField>
    <SomeField other="a">Three</SomeField>
    <SomeField other="v">Four</SomeField>
    <SomeField subCode="XY">Five</SomeField>
    <SomeField>Six</SomeField>
    <SomeField>Seven</SomeField>
    <SomeField other="b">Eight</SomeField>
    <SomeField>Nine</SomeField>
    <SomeField/>
    <SomeField other="x">Eleven</SomeField>
    <SomeField>Twelve</SomeField>
    <SomeField>xThirteen</SomeField>
</Root>

using the following xslt:

<?xml version="1.0"?>
<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="/">
        <Root>
            <xsl:apply-templates/>
        </Root>
    </xsl:template>

    <xsl:template match="Field">
        <xsl:element name="SomeField">
            <xsl:apply-templates select="@*"/>
            <xsl:value-of select="text()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@key['XY']">
        <xsl:attribute name="subCode">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@key[string-length(.)]">
        <xsl:attribute name="other">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@key[not(string-length(.))]" />
</xsl:stylesheet>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文