将相邻注释转换为XSD中的注释:XSD中的注释

时间:2014-08-19 07:06:06

标签: xml xslt xsd xml-comments

我有一个有许多注释的XSD,应该将它们移到前面的xs:simpleTypes或xs:complexTypes的a xs:annotation / xs:documentation部分。如何使用XSLT V1.0或XSLT V2.0移动这些注释?

示例输入XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:simpleType name="ligula">
    <xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="ultricies">
    <xs:restriction base="xs:integer"/>
</xs:simpleType>
<!--
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
Aenean commodo ligula eget dolor. Aenean massa. Cum 
-->
<xs:simpleType name="neque">
    <xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="tincidunt">
    <xs:restriction base="xs:string"/>
</xs:simpleType>
<!-- ligula, porttitor eu, consequat vitae, eleifend ac, enim.  -->
<!-- Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed.  -->
<!-- Integer tincidunt. Cras dapibus. Vivamus elementum  -->
</xs:schema>

输出XSD应为:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:simpleType name="ligula">
        <xs:restriction base="xs:string"/>
    </xs:simpleType>
    <xs:simpleType name="ultricies">
        <xs:annotation>
            <xs:documentation>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
            Aenean commodo ligula eget dolor. Aenean massa. Cum</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:integer"/>
    </xs:simpleType>
    <xs:simpleType name="neque">
        <xs:restriction base="xs:string"/>
    </xs:simpleType>
    <xs:simpleType name="tincidunt">
        <xs:annotation>
            <xs:documentation>ligula, porttitor eu, consequat vitae, eleifend ac, enim</xs:documentation>
            <xs:documentation>Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed.</xs:documentation>
            <xs:documentation>Integer tincidunt. Cras dapibus. Vivamus elementum</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:string"/>
    </xs:simpleType>
</xs:schema>

2 个答案:

答案 0 :(得分:3)

以下样式表将每个评论节点转换为xs:documentation元素。更准确地说,我在一个变量中存储紧跟在xs:simpleTypexs:complexType元素后面的注释节点序列:

<xsl:variable name="com" select="following-sibling::comment() except following-sibling::*[local-name() = 'simpleType' or local-name() = 'complexType'][1]/following-sibling::comment()"/>

该表达式查找作为注释节点的所有后续兄弟,并减去所有注释节点,这些注释节点是紧随其后的xs:simpleTypexs:complexType元素的后续兄弟(我知道,这听起来很复杂)。 / p>

如果此序列不为空:

<xsl:if test="$com">

然后,插入xs:annotation元素,并将每个注释节点的字符串值转换为xs:documentation元素:

<xs:annotation>
  <xsl:for-each select="$com">
     <xs:documentation>
        <xsl:value-of select="normalize-space(.)"/>
     </xs:documentation>
  </xsl:for-each>
</xs:annotation>

其他细节:

  • 如果元素节点与模板匹配,则必须先将所有属性添加到结果树中。将子元素添加到结果树后,不能再添加任何属性节点。
  • 还有另一个模板可以匹配评论节点 - 并且什么都不做,因为它们都是在另一个模板中处理的。

<强>样式表

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />
    <xsl:strip-space elements="*"/>    

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="xs:simpleType|xs:complexType">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:variable name="com" select="following-sibling::comment() except following-sibling::*[local-name() = 'simpleType' or local-name() = 'complexType'][1]/following-sibling::comment()"/>
            <xsl:if test="$com">
                <xs:annotation>
                    <xsl:for-each select="$com">
                        <xs:documentation>
                            <xsl:value-of select="normalize-space(.)"/>
                        </xs:documentation>
                    </xsl:for-each>
                </xs:annotation>
            </xsl:if>

            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="comment()"/>

</xsl:transform>

XML输出

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:simpleType name="ligula">
      <xs:restriction base="xs:string"/>
   </xs:simpleType>
   <xs:simpleType name="ultricies">
      <xs:annotation>
         <xs:documentation>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum</xs:documentation>
      </xs:annotation>
      <xs:restriction base="xs:integer"/>
   </xs:simpleType>
   <xs:simpleType name="neque">
      <xs:restriction base="xs:string"/>
   </xs:simpleType>
   <xs:simpleType name="tincidunt">
      <xs:annotation>
         <xs:documentation>ligula, porttitor eu, consequat vitae, eleifend ac, enim.</xs:documentation>
         <xs:documentation>Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed.</xs:documentation>
         <xs:documentation>Integer tincidunt. Cras dapibus. Vivamus elementum</xs:documentation>
      </xs:annotation>
      <xs:restriction base="xs:string"/>
   </xs:simpleType>
</xs:schema>

如果您想要进行更改,请在线here尝试此解决方案。

答案 1 :(得分:2)

尝试

<xsl:template match="xs:schema">
  <xsl:copy>
    <xsl:for-each-group group-starting-with="xs:simpleType|xs:complexType">
      <xsl:apply-templates select="." mode="include-comments">
        <xsl:with-param name="comments" select="current-group()/self::comment()"/>
      </
    </
  </
</

<xsl:template match="*" mode="include-comments">
  <xsl:param name="comments" as="comment()*"/>
  <xsl:copy>
    <xs:documentation>
      <xsl:for-each select="$comments">
        <xs:annotation><xsl:value-of select="."/>
      </xsl:for-each>
    </
  </
</

注意:在典型的实现中,这可能具有线性性能,而Matthias的解决方案可能具有二次性能。