我有2个输入xml文件。
1)Ant Buld文件:
<project name="project">
<target name="target1"/>
<target name="target2"/>
</project>
2)视觉范式项目:
<Project Name="VpProj" attr1="attr" attr2="attr">
<Models>
<Model Id="O60QwyKGAqACZC5_" Name="ILockXml">
<ModelChildren>
<!-- THE FOLLOWING PACKAGE DOES NOT NEED TO BE INCLUDED IN OUTPUT,
IS GIVEN AS EXAMPLE -->
<Package Id="tYTQwyKGAqACZC6R" Name="Xml Files">
</Package>
<!-- I WANT TO INSERT NEW PACKAGE ELEMENTS HERE, SUPPOSE A FORM OF: -->
<!--
<Package Id="NEWGUID!" Name="target1">
</Package>
<Package Id="NEWGUID!" Name="target2">
</Package>
-->
</ModelChildren>
</Model>
</Models>
</Project>
我的输出需要具有上面的形式,但没有“Xml Files”包。
我正在使用Saxon HE,我是XSL的新手。到目前为止,我有以下内容......
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<!-- THIS IS THE VpProj FILE -->
<xsl:variable name="prj" select="document('vp-xml/project.xml')"/>
<xsl:template match="/">
<xsl:for-each select="$prj/Project">
<!-- ______ I AM HERE _____ -->
<!-- HOW DO I INJECT THE ENTIRE PROJECT ELEMENT TAG HERE? -->
</xsl:for-each>
</xsl:template>
</xsl:transform>
我正在命令行上传递Ant Build文件。我知道如何将更多的文字代码包装在我正在创建的包中,我希望在这个阶段的答案看起来像:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<!-- THIS IS THE VpProj FILE -->
<xsl:variable name="prj" select="document('vp-xml/project.xml')"/>
<xsl:template match="/">
<xsl:for-each select="$prj/Project">
<!-- ______ I AM HERE _____ -->
<!-- HOW DO I INJECT THE ENTIRE PROJECT ELEMENT TAG HERE? -->
<XSL:INJECT-VP-ELEMENT-MAGIC>
<Model Id="O60QwyKGAqACZC5_" Name="ILockXml">
<ModelChildren>
<xsl:template match="/project"/>
</ModelChildren>
</Model>
</XSL:INJECT-VP-ELEMENT-MAGIC>
</xsl:for-each>
</xsl:template>
<xsl:template match="/project">
<xsl:for-each select="target">
<Package>
<xsl:attribute name="Name">
<xsl:value-of select="./@name"/>
</xsl:attribute>
<xsl:attribute name="Id">
<!-- NEED HELP WITH GUID TOO, IS TRUE GUID POSSIBLE WITH SAXON HE? -->
</xsl:attribute>
</Package>
</xsl:for-each>
</xsl:template>
</xsl:transform>
这个东西很难找到,但我到了那里。
当我说注入整个项目元素标记时,我想一般地这样做,而不是创建对元素名称及其属性的文字引用,即:
<Project>
<xsl:attribute name="Name">
<xsl:value-of select="$prj/Project/@name"/>
</xsl:attribute>
<!-- etc... DO NOT WANT THIS FORM -->
</Project>
答案 0 :(得分:1)
忘掉for-each
。如果您想要一个对现有XML进行调整的XSLT,并且大部分都保持不变,那么通常的方法是将其基于身份转换。然后编写与要修改的内容匹配的特定模板。以下是我将如何解决这一特定问题:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<!-- This is the build.xml - you need to save this in a variable because the
meaning of "/" changes when you're processing nodes from a different
document -->
<xsl:variable name="build" select="/" />
<!-- identity transformation - copy everything as-is unless overridden -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- starting point -->
<xsl:template match="/">
<!-- process the project.xml document. Note that we have to process
document(...)/node() rather than just document(...) as the latter
would match this current template, leading to an infinite loop -->
<xsl:apply-templates select="document('vp-xml/project.xml')/node()" />
</xsl:template>
<!-- behave like the identity template, but also process the build file -->
<xsl:template match="ModelChildren">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
<xsl:apply-templates select="$build//target" />
</xsl:copy>
</xsl:template>
<!-- logic to handle target elements from the build file -->
<xsl:template match="target">
<Package Name="{@name}" />
<!-- and whatever else you need to do here -->
</xsl:template>
</xsl:stylesheet>
要生成唯一标识符,XSLT具有generate-id
功能,但未指定这些标识符的格式 - 不同的处理器可以以不同的格式生成它们,只要您始终为同一节点获取相同的ID并且在给定的转换运行期间,不同节点的不同ID。如果您特别需要随机ID来跟随问题中的格式,那么您可能必须使用随机数生成器自己处理它,但默认情况下在Saxon HE中没有 - 如果您有 PE 然后你可以使用EXSLT random-sequence
函数:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:rnd="http://exslt.org/random" exclude-result-prefixes="rnd">
<xsl:variable name="idChars" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_'" />
<!-- rest of stylesheet as before -->
<!-- logic to handle target elements from the build file -->
<xsl:template match="target">
<Package Name="{@name}" Id="{string-join(
for $num in rnd:random-sequence(16, position())
return substring($idChars, $num * string-length($idChars) + 1, 1),
'')}"/>
<!-- and whatever else you need to do here -->
</xsl:template>
</xsl:stylesheet>