1

Timed Text Markup Language(TTML)ドキュメントの非常に単純な変換を実行しようとしています。TTMLファイルの最小限の例を次に示します。

<?xml version="1.0" encoding="UTF-8"?>
<tt xml:lang="en" xmlns="http://www.w3.org/2006/04/ttaf1"
    xmlns:tts="http://www.w3.org/2006/04/ttaf1#styling">
    <head>
    </head>
    <body>
        <div xml:lang="en" style="1">
            <p begin="00:00:00.20" dur="00:00:02.26">&gt;&gt; One time entry<br/>with a line break.</p>
        </div>
    </body>
</tt>

ドキュメントのデフォルトの名前空間に注意してください。それが私が抱えている問題の鍵です。

これが私が使用している変換です。これがすべてです、それは非常に簡単です。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
    xmlns:tt="http://www.w3.org/2006/04/ttaf1">
    <xsl:output method="text" indent="yes" />
    <xsl:strip-space elements="*" />
    <xsl:preserve-space elements="tt:p"/>

    <!-- The indentation of the close tag for the following node is crucial to the transformed layout. Don't move it! -->
    <xsl:template match="tt:p"><xsl:apply-templates />&#160;
</xsl:template>

    <xsl:template match="tt:p/text()"><xsl:copy />&#160;</xsl:template>

</xsl:stylesheet>

私たちのデータセットには何百ものドキュメントがあり、それらすべてに同じデフォルトの名前空間があるわけではありません。ただし、上記のXSLTからわかるように、変換は単純であり、コアデータ要素に基づいている<p />ため、最終的に名前空間のバリエーションは重要ではありません。

XSLTファイルには明示的に定義された名前空間プレフィックス()があるため、上記のXSLは現在一部のソースファイルで機能しますtt。ただし、これは、デフォルトの名前空間が異なる別のソースファイルに遭遇した場合は機能しません。

したがって、既知のプレフィックスに対して任意の未知の名前空間値をXSLTに提供する方法を見つける必要があります。ソースドキュメントのデフォルトの名前空間を見つけるために使用できるコードがあります。

XPathDocument sourceDoc = new XPathDocument("sourcefile.xml");
XPathNavigator sourceNav = sourceDoc.CreateNavigator();
sourceNav.MoveToFollowing(XPathNodeType.Element);
var sourceNS = sourceNav.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml);
string defNS = sourceNS.Single(n => n.Key =="").Value;

これは正しく私に与えますhttp://www.w3.org/2006/04/ttaf1。しかし、私はこの値をどうするか理解できないようです。XslCompiledTransform私は何時間もの間、インスタンスに変数の名前空間を提供しようとして検索し、実験してきました。トランスフォーム自体の領域内には、それを取得できるものは何もないようです。

XmlDocument名前テーブルを操作するために、XSLTファイルをに明示的にロードしようとしました(xmlns:tt="..."上記のXSLTで明示的な名前空間宣言を削除した後)。

XslCompiledTransform objXsl = new XslCompiledTransform();
StringWriter writer = new StringWriter();
XPathDocument sourceDoc;
XmlDocument xslDoc = new XmlDocument();
XPathNavigator sourceNav, xslNav;
XmlNamespaceManager xslNsManager;

sourceDoc = new XPathDocument("sourcefile.xml");
sourceNav = sourceDoc.CreateNavigator();
sourceNav.MoveToFollowing(XPathNodeType.Element);
var sourceNS = sourceNav.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml);

xslDoc.Load("transform.xslt");

xslNsManager = new XmlNamespaceManager(xslDoc.NameTable);
xslNsManager.AddNamespace("tt", sourceNS.Single(n => n.Key =="").Value);

xslNav = xslDoc.CreateNavigator();
objXsl.Load(xslNav);

objXsl.Transform(sourceNav, null, writer);

これは実際の変換まで実行され、そこで私は次のようにXslLoadException述べますPrefix 'tt' is not defined.

私はこの時点で途方に暮れています。検索から見つけることができるすべてのことは、名前空間をXSLTドキュメントに入れることについて説明しています(私はすでに持っていて、1つの名前空間値に対して正常に機能します)。名前空間の定義をその場でトランスフォームに追加する方法を説明しているMSDNドキュメントやその他の場所には何も見つかりません。

誰かアイデアはありますか?

4

2 に答える 2

1

同僚は、XSL ドキュメントに変数の名前空間を追加/操作することを勧めました。名前テーブルの変更を使用した私の試みは正しい方向に向かっていましたが、うまくいきませんでした。彼の提案に基づいて私が思いついたのは次のとおりです。

XslCompiledTransform xslXform = new XslCompiledTransform();
StringWriter writer = new StringWriter();
XmlDocument xslDoc = new XmlDocument();
XPathNavigator sourceNav;

sourceNav = new XPathDocument(sourceFile).CreateNavigator();
sourceNav.MoveToFollowing(XPathNodeType.Element);
var sourceNS = sourceNav.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml);
string ttNamespace = sourceNS.Single(n => n.Key == "").Value;

xslDoc.Load(xslFile);
xslDoc.DocumentElement.SetAttribute("xmlns:tt", ttNamespace);
xslXform.Load(xslDoc.CreateNavigator());
xslXform.Transform(sourceNav, null, writer);

これは機能しますが、私には少しハックな気がします。Xml中心的な問題は、 ( | XPath)Document型とそれに関連付けられている名前テーブル/名前空間マネージャーとの関係を理解し​​ていないことだと思います。

于 2011-10-26T15:05:27.497 に答える