XSLT:复制当前类型值等于元素名称的位置

时间:2009-07-08 18:28:13

标签: xslt

使用this file作为源,我需要从本地源文件或导入中记录的相关源文件中检索元素。类型值使用冒号分隔两个值 - substring-before(@type,':')告诉我要引用哪个文件; substring-after(@ type,':')是我需要复制的文件中元素的名称。以相同的方式迭代其内容。

示例:我想要xs:complexType,其名称为“PersonType”,因此我使用copy-of来抓取它及其子节点。下一步是查看那些子项 - 对于那些xs:element,我想检索类型值(“AcRec:HighSchoolType”)中引用的元素。 “AcRec”告诉我需要使用哪个xsd,所以我知道我会在xsd中找到名称值为“HighSchoolType”的内容。看看AcRec xsd,我知道“HighSchoolType”是一个xs:complexType(我已经定义了一个模板来处理)所以我应该看到输出。

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/">
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:core="urn:org:pesc:core:CoreMain:v1.2.0" xmlns:AcRec="urn:org:pesc:sector:AcademicRecord:v1.1.0">
    <xsl:apply-templates select="//xs:complexType[@name='PersonType']" />       
</xs:schema>
</xsl:template> 

<xsl:template match="xs:complexType">
    <xsl:copy>
        <xsl:copy-of select="node()[not(xs:annotation | xs:restriction)]|@*"/>
    </xsl:copy>
    <xsl:apply-templates select=".//xs:element" />
</xsl:template>

<xsl:template match="xs:simpleType">
    <xsl:copy>
        <xsl:copy-of select="node()|@*"/>
    </xsl:copy>
</xsl:template> 

<xsl:template match="xs:element">
    <xsl:choose>
        <xsl:when test="substring-before(@type, ':') = 'AcRec'">
            <xsl:text>AcRec</xsl:text>
            <xsl:apply-templates select="document('[local file path]AcademicRecord_v1.3.0.xsd')//*[@name=substring-after(@type, ':')]" />
        </xsl:when>                     
    </xsl:choose>
</xsl:template>

所需的输出如下:

<xs:complexType name="PersonType">
  <xs:sequence>
    <xs:element name="HighSchool" type="AcRec:HighSchoolType" minOccurs="0">
  </xs:sequence>
</xs:complexType>
<xs:complexType name="HighSchoolType">
  <xs:sequence>
    <xs:element name="OrganizationName" type="core:OrganizationNameType"/>
    <xs:group ref="core:OrganizationIDGroup" minOccurs="0"/>
  </xs:sequence>
</xs:complexType>

当我成功进入xsl时,我在文档中查看的内容是什么? xsl:text告诉我我在,但后续行没有返回输出。

此外,如何在复制xs时排除xs:annotation和xs:restriction元素:complextType&amp; xs:simpleType元素?我无法让dpawson网站上提到的例子起作用。

2 个答案:

答案 0 :(得分:0)

我必须说,并且不要冒犯,你的问题真的很难理解;你能把它分解一下吗?

同时,就排除xs:annotation和xs:restriction元素而言,只需更改你的copy-of语句就可以了解它们:

<xsl:copy-of select="node()[not(self::xs:annotation or self::xs:restriction)]|@*"/>

...你有一个 xsl:choose 元素只有一个 xsl:when 而没有 xsl:否则 ...你可以使用 xsl:if 元素简化此操作:

<xsl:template match="xs:element">
   <xsl:if test="substring-before(@type, ':') = 'AcRec'">
     <xsl:text>AcRec</xsl:text>
       <xsl:apply-templates select="document('[local file path]AcademicRecord_v1.3.0.xsd')//*[@name=substring-after(@type, ':')]" />
   </xsl:if>
</xsl:template>

进一步反思后,看起来您的select语句可能格式错误:当前它正在尝试匹配冒号后具有与type属性匹配的name属性的任何元素。所以匹配必须是

<element name="text" type="some:text"/>

如果您没有这样的元素,那么您的匹配为空,因此不会运行任何模板。

答案 1 :(得分:0)

问题是:

<xsl:apply-templates select="document('[local file path]AcademicRecord_v1.3.0.xsd')//*[@name=substring-after(@type, ':')]" />

......应该是:

<xsl:variable name="name" select="substring-after(@type, ':')" />
<xsl:apply-templates select="document('[local file path]AcademicRecord_v1.3.0.xsd')//*[@name=$name]" />

ScottSEA - 当你说它是基于以下的比较时你是对的:

<element name="text" type="some:text"/>

在XPath表达式的处理过程中会涉及上下文切换。当您说// * [@ name = substring-after(@ type,':')]时,您说“将此模板应用于引用的XSD文档中具有@name和@type属性的元素,并且其@name等于THEIR @type的':'之后的子串。然而,如果你使用一个变量,你当然会得到当前文档中的substring-after。