更改XSLT中的属性值

时间:2017-11-24 07:38:43

标签: xml xslt

我有一个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>

1 个答案:

答案 0 :(得分:0)

这里有两个问题:

  • 您正在匹配SQLiteFieldSink元素上的所有属性,并将所有替换为let gradientStart = UIColor.orange let gradientEnd = UIColor.blue final class BorderedButton: UIButton { private let gradient = CAGradientLayer() private let shapeLayer = CAShapeLayer() override func layoutSubviews() { super.layoutSubviews() let radius = bounds.size.height / 2 let outside = UIBezierPath(roundedRect: CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height), cornerRadius: radius) let inside = UIBezierPath(roundedRect: CGRect(x: 3.0, y: 3.0, width: bounds.width - 6, height: bounds.height - 6), cornerRadius: radius - 3) outside.append(inside) outside.usesEvenOddFillRule = true shapeLayer.path = outside.cgPath gradient.frame = CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height) } init(color: UIColor?, frame: CGRect = .zero) { super.init(frame: frame) let isGradient = color == nil shapeLayer.fillRule = kCAFillRuleEvenOdd //gradient part gradient.colors = isGradient ? [gradientStart.cgColor, gradientEnd.cgColor] : [color!.cgColor, color!.cgColor] gradient.startPoint = CGPoint(x: 0.2, y: 0.5) gradient.endPoint = CGPoint(x: 1, y: 1) gradient.mask = shapeLayer layer.addSublayer(gradient) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 属性
  • 您正在使用绝对路径(在connectionString中)选择属性,而该路径并未考虑他们实际所属的父级。

您需要使用相对路径来定位节点。我认为以下是您的实际目标:

for-each

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

<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>
相关问题