2017-11-24 21 views
0

XslCompiledTransformを使用してXSLT変換の助けを借りてXML構造を新しい構造にコピーするC#アプリケーションがあります。私はXSLTの初心者ですが、今は自分のXSLTコードに固執しています。XSLTの属性の値を変更する

<?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> 
: 私はこの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ファイル)が表示されます。これは、検索パスに同じ文字列を使用しているようで、ファイル名が最後に間違っているために間違っています。両方の要素は、任意のヘルプははるかに高く評価されるのと同じファイル・エンディング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> 
+0

FYI 'XslCompiledTransform' doesnのXSLT 2.0をサポートしていません。実際には2.0の機能を使用していないので、バージョンを1.0に変更する必要があります。 – JLRishe

答えて

0

二つの問題がここにあります

  • あなたはSQLiteFieldSink要素上すべての属性を照合し、それらにを交換するすべての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> 
+0

ありがとう!あなたの修正は完璧に動作します、ありがとうございます! – Robert

関連する問題