我正在尝试对定时文本标记语言 (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">>> 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 /> 
</xsl:template>
<xsl:template match="tt:p/text()"><xsl:copy /> </xsl:template>
</xsl:stylesheet>
我们的数据集有数百个文档,它们并不都具有相同的默认命名空间。但是,正如您从上面的 XSLT 中看到的那样,转换很简单并且基于核心数据元素<p />
,因此最终命名空间变化并不重要。
由于 XSLT 文件具有明确定义的名称空间前缀 ( tt
),因此上述 XSL 当前适用于某些源文件。但是,当遇到另一个具有不同默认命名空间的源文件时,这不起作用。
所以我需要找到一种方法,为 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
实例提供变量命名空间。似乎在变换本身的区域内没有任何东西可以接受它。
我已经尝试将 XSLT 文件显式加载到一个XmlDocument
中以操作名称表(在删除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 文档(我已经拥有,它适用于一个名称空间值)。我在 MSDN 文档或其他地方找不到任何解释如何将命名空间定义动态添加到转换中的内容。
有人有想法么?