我是XML和XSL Stylesheets的新手,我的任务是为我们的一个客户创建样式表。我已经创建了一个样式表,它以下列格式输出XML:
<Trip TripType="Normal">
<Plan BeginTime="2011-08-13T10:00:00" UserDefinedTripID="777" UserDefinedRouteID="777">
<PlanStop ArrivalTime="2011-08-13T15:30:00" ArrivalLock="true" SiteID="1" PassThru1="test1" PassThru2="test2" PassThru3="test3" PassThru4="test4">
<PlanNote Line1="Freeform Text" Line2="Line2" Line3="Line3" />
<PlanCargo Duration="60" BillID="" Weight="100" Units="100.0" XUnitTypeID="10" Action="Pick" />
<PlanNote Line1="Freeform Text" Line2="Line2" Line3="Line3" />
<PlanCargo Duration="60" BillID="" Weight="100" Units="100.0" XUnitTypeID="12" Action="Pick" />
</PlanStop>
</Plan>
</Trip>
我需要获取输出并将内容插入Trip元素中的属性,如下所示:
<Trip TripID="-1" CurrentRevisionNumber="1" IsDispatch="1" IsActive="0"
IsComplete="0" OrganizationID="4"
TripData="<Trip TripType="Normal">
<Plan BeginTime="2011-08-13T10:00:00" UserDefinedTripID="777"
UserDefinedRouteID="777">
<PlanStop ArrivalTime="2011-08-13T10:00:00" ArrivalLock=& quot;true" SiteID="1" PassThru1="test1" PassThru2=& quot;test2" PassThru3="test3" PassThru4="test4">
<PlanCargo Duration="45" BillID="" Weight=& quot;100" Units="100.0" XUnitTypeID="9" Action="Pick" />
</PlanStop> />
换句话说,我需要获取现有的XML输出,并在执行某些字符转换时将其放在属性中。
是的,它非常难看,但这就是他们想要的。我正在考虑制作另一个XSL,它将复制原始XSL转换的XML输出并将其放在属性中,同时将&lt;,&gt;,“等转换为&lt;,&gt;,”等等(不知道是什么他们被称为)。
我已经在互联网上寻找解决方案,但我似乎找不到任何类似的东西(我想这是因为这是一个荒谬的请求)。如有必要,我可以提供我原来的XSL,但如果可能的话,我宁愿不改变它。
提前致谢!
答案 0 :(得分:3)
我必须同意其他评论者的观点,即在属性中插入XML文档作为词法XML是完全疯狂的。数据的所有者将失去如此多的权力和灵活性,并获得任何回报。但是,如果你真的别无选择,那就自杀(笑话)。如果此选项对您来说不合适,那么您可以使用类似的模板序列化内部XML ...
<xsl:template match="*" mode="serialise">
<xsl:value-of select="concat('<',local-name(),' ')">
<xsl:apply-templates select="@*" mode="serialise">
<xsl:value-of select="' >'">
<xsl:apply-templates select="*|text()" mode="serialise">
<xsl:value-of select="concat('</',local-name(),' >')">
</xsl:template>
<xsl:template match="@*" mode="serialise">
<xsl:value-of select="concat(local-name(),'="',.,'" ')">
</xsl:template>
<xsl:template match="text()" mode="serialise">
<xsl:value-of select=".">
</xsl:template>
将要编码的内部结构的根元素作为词法XML并调用&lt; xsl:apply-templates&gt;使用@ mode =“serialise”。将此调用的输出捕获到字符串变量中。然后,您可以在您喜欢的结果树中的what-ever属性中插入字符串变量的内容。
这些简单的模板不处理comments(),processing-instructions()和DocTypes。此外,根据XDM(与DOM相反),将合并相邻的文本类型节点(文本,CDATA,字符引用等)。这也不适用于名称空间。
答案 1 :(得分:3)
我可以节省自己的时间,努力和抑郁,避免别人的愚蠢,并通过一个使用微小扩展功能的微小转变实现这一点。
以下是使用.NET XslCompiledTransform XSLT处理器的示例:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:my="my:my" exclude-result-prefixes="msxsl my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<t stupid="{my:stringize(.)}"/>
</xsl:template>
<msxsl:script language="c#" implements-prefix="my">
public string stringize(XPathNavigator doc)
{
return doc.InnerXml;
}
</msxsl:script>
</xsl:stylesheet>
当应用于任何XML文档时,它会生成带有stupid
属性的顶部元素,该属性包含顶部元素主体的转义表示。
例如,在此XML文档上应用转换时:
<t>
<a>
<b x="y">
<!-- Comment here -->
<?aPI ?>
</b>
</a>
</t>
生成了想要的结果:
<t stupid="
 <a>
 <b x="y">
 <!-- Comment here -->
 <?aPI?>
 </b>
 </a>
" />
实现相同想法的转换最有可能为几乎每个XSLT处理器编写,其扩展函数本身可以用各种编程语言编写。
答案 2 :(得分:2)
可以在http://code.google.com/p/httpfox/source/browse/trunk/chrome/content/XMLPrettyPrint.xsl?r=3找到用于将XML序列化为转义文本的XSLT样式表。它输出HTML,但您可以轻松地将其调整为输出XML,主要是通过删除不需要的东西,如扩展器。
唯一棘手的部分可能是从现有XSL获取XML输出作为新模板的输入。如果将后者作为单独的样式表实现,或者如果使用XSLT 2.0,则没有问题。否则,您可能需要使用node-set()
扩展功能。
以上几个方面可以详细说明。霍勒,如果你卡住了! HTH。
P.S。实际上,自从我开始这篇文章以来,@ Sean发布了他的答案,并且比使用上述样式表更容易使用。
答案 3 :(得分:2)
基本上,您需要序列化XML,将序列化的结果捕获为字符串,然后使用此字符串作为其值来编写属性。在XSLT 1.0或XSLT 2.0中没有直接的方法。 XSLT 3.0有一个函数fn:serialize(),旨在满足这一要求,并在最新版本的Saxon中实现。 (早期版本的Saxon使用saxon:serialize()扩展函数引入了这个想法。您可以在其他产品中找到类似的函数,或者您也可以编写自己的函数。)在XSLT中实现序列化程序当然是可能的,如其他人建议;它只是相当乏味。