【问题标题】:Change value of attributes in XSLT更改 XSLT 中的属性值
【发布时间】:2017-11-24 15:59:12
【问题描述】:

我有一个 C# 应用程序,可以在 XslCompiledTransform 的 XSLT 转换的帮助下将 XML 结构复制到新的结构中。我是 XSLT 的初学者,现在我有点卡在我的 XSLT 代码上。 我希望此 XSLT 转换更改特定类型的所有元素的搜索路径,并在属性中使用匹配模式(从 Linux 文件路径到 Windows)

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:from="http://example.com/schema/FieldSinks/v1.xsd" xmlns:sqlite="http://example.com/schema/SQLiteFieldSink/v1.xsd" 
xmlns:fn="http://www.w3.org/2005/02/xpath-functions">

 <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
 <xsl:strip-space elements="*"/>

  <xsl:param name="winsrc">c:\data\</xsl:param>
  <xsl:param name="linuxsrc">/var/persistent/data/</xsl:param>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

  <xsl:template match="from:FieldSinkRoot//sqlite:SQLiteFieldSink/@*">
    <xsl:for-each select="//sqlite:SQLiteFieldSink/@*[contains(.,'/var/persistent/data/')]">

      <xsl:variable name="str" select='.' />
      <xsl:variable name="str2" select="substring-before($str, $linuxsrc)" />
      <xsl:variable name="str3" select="substring-after($str, $linuxsrc)" />
      <xsl:variable name="str4" select="concat($str2,$winsrc)" />
      <xsl:variable name="str5" select="concat($str4,$str3)" />
      <xsl:attribute name="connectionString"><xsl:value-of select="$str5 "/></xsl:attribute>
    </xsl:for-each>

  </xsl:template>
</xsl:stylesheet>

使用这个输入文件:

<?xml version="1.0" encoding="utf-8"?>

<FieldSinkRoot id="FieldSinksRoot" xmlns="http://example.com/schema/FieldSinks/v1.xsd">
    <SQLiteFieldSink 
      id="HourValues"  
      idleTimeout="5000" 
      connectionString="Data Source=/var/persistent/data/fsSQLiteHour.db;Version=3;"  
      warningSearchLevel="2000" 
      warningOnZeroResults="false" 
      deleteOldFields="true" 
      keepFieldsInMonth="24" 
      xmlns="http://example.com/schema/SQLiteFieldSink/v1.xsd" >
    </SQLiteFieldSink>
    <SQLiteFieldSink 
      id="MinuteValues"  
      idleTimeout="5000"
      connectionString="Data Source=/var/persistent/data/fsSQLiteMinute.db;Version=3;"  
      warningSearchLevel="2000" 
      warningOnZeroResults="false" 
      deleteOldFields="true" 
      keepFieldsInMonth="24"
      xmlns="http://example.com/schema/SQLiteFieldSink/v1.xsd" >
    </SQLiteFieldSink>
    <LocalDatabaseFieldSink 
      id="Localhost" 
      idleTimeout="5000" 
      warningSearchLevel="1000" 
      warningOnZeroResults="true" 
      xmlns="http://example.com/schema/LocalDatabaseFieldSink/v1.xsd" />
</FieldSinkRoot>

我得到这个输出文件(新的 XML 文件),这是错误的,因为它看起来使用相同的字符串作为搜索路径并且文件名最终是错误的。两个元素获得相同的文件结尾 fsSQLiteMinute.db 而不是 fsSQLiteHour.db

任何帮助将不胜感激。

<?xml version="1.0" encoding="utf-8"?>
<FieldSinkRoot id="FieldSinksRoot" xmlns="http://example.com/schema/FieldSinks/v1.xsd">
  <SQLiteFieldSink 
    connectionString="Data Source=c:\data\fsSQLiteMinute.db;Version=3;" 
    xmlns="http://example.com/schema/SQLiteFieldSink/v1.xsd" />
  <SQLiteFieldSink 
    connectionString="Data Source=c:\data\fsSQLiteMinute.db;Version=3;" 
    xmlns="http://example.com/schema/SQLiteFieldSink/v1.xsd" />
  <LocalDatabaseFieldSink 
    id="Localhost" 
    idleTimeout="5000" 
    warningSearchLevel="1000" 
    warningOnZeroResults="true" 
    xmlns="http://example.com/schema/LocalDatabaseFieldSink/v1.xsd" />
</FieldSinkRoot>

【问题讨论】:

  • 仅供参考 XslCompiledTransform 不支持 XSLT 2.0。您实际上并没有使用任何 2.0 功能,因此您应该将版本更改为 1.0。

标签: xml xslt


【解决方案1】:

这里有两个问题:

  • 您正在匹配 SQLiteFieldSink 元素上的 all 属性,并将它们 all 替换为 connectionString 属性
  • 您正在使用绝对路径(在您的 for-each 中)选择属性,该路径未考虑它们实际属于哪个父级。

您需要使用相对路径来定位节点。我认为以下是您真正想要的:

<xsl:template match="sqlite:SQLiteFieldSink/@*[contains(.,'/var/persistent/data/')]">
  <xsl:attribute name="{ name() }">
    <xsl:variable name="before" select="substring-before(., $linuxsrc)" />
    <xsl:variable name="after" select="substring-after(., $linuxsrc)" />

    <xsl:value-of select="concat($before, $winsrc, $after)"/>
  </xsl:attribute>
</xsl:template>

当该模板在您的 XSLT 中被替换并针对您的输入运行时,结果是:

<FieldSinkRoot id="FieldSinksRoot" xmlns="http://example.com/schema/FieldSinks/v1.xsd">
  <SQLiteFieldSink 
    id="HourValues" 
    idleTimeout="5000" 
    connectionString="Data Source=c:\data\fsSQLiteHour.db;Version=3;" 
    warningSearchLevel="2000" 
    warningOnZeroResults="false" 
    deleteOldFields="true" 
    keepFieldsInMonth="24" 
    xmlns="http://example.com/schema/SQLiteFieldSink/v1.xsd" />
  <SQLiteFieldSink 
    id="MinuteValues" 
    idleTimeout="5000" 
    connectionString="Data Source=c:\data\fsSQLiteMinute.db;Version=3;" 
    warningSearchLevel="2000" 
     warningOnZeroResults="false" 
    deleteOldFields="true"
    keepFieldsInMonth="24" 
    xmlns="http://example.com/schema/SQLiteFieldSink/v1.xsd" />
  <LocalDatabaseFieldSink 
    id="Localhost" 
    idleTimeout="5000" 
    warningSearchLevel="1000" 
    warningOnZeroResults="true" 
    xmlns="http://example.com/schema/LocalDatabaseFieldSink/v1.xsd" />
</FieldSinkRoot>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多