2

我有以下问题,请参阅代码示例:

<xsl:if test="/Document/test/id">
  <TEST1>
     <xsl:value-of select="/Document/test/id"/>
   </TEST1>
</xsl:if>

我有一个巨大的 xslt 脚本,里面有很多相同的代码。我想创建一个函数,但我总是遇到错误。我在问自己这是否是解决这个问题的正确解决方案。

为了使代码更好地维护,我想使用类似下面的东西。这不是 xslt 语法,因为我不知道怎么做,而是想知道我在寻找什么。

...
<xsl:something "TEST1", "/Document/test/id1" />
<xsl:something "TEST2", "/Document/test/id2" />
...

尽管我不知道如何解决这个问题,但代码的可读性和可维护性会更好:-(欢迎任何建议......

问候德克

4

2 回答 2

2

这种转变

<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:my="my:my" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vDoc" select="/"/>

 <xsl:template match="/">
     <xsl:sequence select="my:test(xs:QName('Test1'), /*/test/id1/string())"/>
     <xsl:sequence select="my:test(xs:QName('Test2'), /*/test/id2/string())"/>
     <xsl:sequence select="my:test(xs:QName('Test3'), /*/test/id3/string())"/>
     <xsl:sequence select="my:test(xs:QName('Test4'), /*/test/id4/string())"/>
 </xsl:template>

 <xsl:function name="my:test">
   <xsl:param name="pName" as="xs:QName"/>
   <xsl:param name="pToPresent" as="item()?"/>

   <xsl:if test="$pToPresent">
     <xsl:element name="{$pName}">
             <xsl:sequence select="$pToPresent"/>
     </xsl:element>
   </xsl:if>
 </xsl:function>
</xsl:stylesheet>

应用于以下 XML 文档时:

<Document>
 <test>
  <id1>Some Id1</id1>
 </test>
 <test>
  <id2>Some Id2</id2>
 </test>
 <test>
  <id4>Some Id4</id4>
 </test>
</Document>

产生了想要的正确结果:

<Test1>Some Id1</Test1>
<Test2>Some Id2</Test2>
<Test4>Some Id4</Test4>

请注意

  1. 的第一个参数my:test()声明为 type xs:QName,它保证指令的name属性值xsl:element始终是有效名称。

  2. 的第二个参数my:test()被非常松散地声明为 type item()?,这使我们可以自由地提供任何类型的项目(字符串或节点或元素,或...),并且所提供的内容将“按原样”复制。

于 2013-03-02T16:25:06.663 回答
2

我认为这是最接近你想要的:

<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:f="custom-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="/">
    <CONTENT>
      <xsl:sequence select="f:rename('TEST1', /Document/test/id1)"/>
      <xsl:sequence select="f:rename('TEST2', /Document/test/id2)"/>
    </CONTENT>
  </xsl:template>

  <xsl:function name="f:rename">
    <xsl:param name="name" as="xs:string"/>
    <xsl:param name="toWrap" />

    <xsl:if test="$toWrap">
      <xsl:element name="{$name}">
        <xsl:value-of select="$toWrap"/>
      </xsl:element>
    </xsl:if>
  </xsl:function>
</xsl:stylesheet>

在以下输入上运行时:

<Document>
  <test>
    <id1>Hello!</id1>
    <id2>Hello again!</id2>
  </test>
</Document>

产生的输出是:

<CONTENT>
   <TEST1>Hello!</TEST1>
   <TEST2>Hello again!</TEST2>
</CONTENT>

您也可以试试这个,它有点冗长,但与 XSLT 1.0 兼容:

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

  <xsl:template match="/">
    <CONTENT>
      <xsl:apply-templates select="/Document/test/id1" mode="rename">
        <xsl:with-param name="name" select="'TEST1'" />
      </xsl:apply-templates>
      <xsl:apply-templates select="/Document/test/id2" mode="rename">
        <xsl:with-param name="name" select="'TEST2'" />
      </xsl:apply-templates>
    </CONTENT>
  </xsl:template>

  <xsl:template match="@* | node()" mode="rename">
    <xsl:param name="name" />
    <xsl:element name="{$name}">
      <xsl:value-of select="." />
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

在上面的示例 XML 上运行时,再次生成相同的输出。

于 2013-03-02T17:27:08.607 回答