【问题标题】:Match an element with a dynamic attribute value匹配具有动态属性值的元素
【发布时间】:2014-06-22 11:31:47
【问题描述】:

我正在尝试原型转换以将xsl:schema 转换为 php 接口。我在匹配具有与xsd:element 元素的type 属性匹配的name 属性的xsd:simpleType 元素时遇到了一些问题。假设我有这样的架构:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="Foo" type="Bar"/>
  <xsd:simpleType name="Bar">
    <xsd:restriction base="xsd:string">
      <xsd:maxLength value="32"/>
    </xsd:restriction>
  </xsd:simpleType>
</xsd:schema>

我希望得到以下结果。

<?php
interface Foo {
  public abstract function buildFooXmlString(Bar $a);
}

这是我目前拥有的 xslt:

<xsl:stylesheet version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="*"/>
  <xsl:template match="/">&lt;?php <xsl:apply-templates select="xsd:schema"/></xsl:template>
  <xsl:template match="xsd:schema">interface FromXsd { <xsl:apply-templates select="xsd:element"/> }</xsl:template>
  <xsl:template match="xsd:element">
    <xsl:apply-templates select="xsd:annotation"/>
    abstract public function build<xsl:value-of select="normalize-space(@name)"/>XmlString(<xsl:apply-templates select="@type"/>);
  </xsl:template>
  <xsl:template match="xsd:annotation">/* <xsl:value-of select="normalize-space()"/> */</xsl:template>

  <xsl:template match="@type"><xsl:apply-templates select="//xsd:simpleType[@name=normalize-space()]"/></xsl:template>
  <xsl:template match="xsd:simpleType"><xsl:value-of select="local-name()"/> $a</xsl:template>
</xsl:stylesheet>

它产生了大部分期望的结果,但不包括括号内的任何内容:

<?php
interface Foo {
  public abstract function buildFooXmlString();
}

如何选择name 属性与element 的type 匹配的simpleType 节点? (对于 xsd 类型,名称必须是唯一的。)

【问题讨论】:

    标签: php xml xslt xpath xsd


    【解决方案1】:

    永远不会选择simpleType 节点,因为在匹配xsd:schema 的模板中,您只将模板应用于xsd:element 子子树。 xsd:simpleType 兄弟将永远不会被处理。

    如果您想允许处理一个节点的所有子节点,您应该在xsd:schema 模板中包含一个空的&lt;xsl:apply-templates/&gt;。

    这仍然不会产生你想要的结果。它实际上要简单得多。要生成你期望的代码片段,你不需要读取xsd:simpleType元素,因为包含你想要的类型的属性可以使用xsd:value-of直接从xsd:element的@type属性中获取,并且你可以在它之后立即打印$a:

    XmlString(<xsl:value-of select="@type"/> $a)
    

    由于您正在生成文本,因此您应该使用&lt;xsl:text&gt; 元素来控制空格的分布方式。例如,如果您使用:

    <xsl:template match="/">
        <xsl:text>&lt;?php </xsl:text>
        <xsl:apply-templates select="xsd:schema"/>
    </xsl:template>
    

    您不必担心总是将&amp;lt;?php 文本放在&lt;xsl:template&gt; 之后,并且可以正常缩进您的代码。您还可以包含带有 &amp;#xa; 字符的换行符(它不会破坏您的格式):

    <xsl:template match="xsd:schema">
        <xsl:text>interface FromXsd {&#xa;</xsl:text>
        <xsl:apply-templates select="xsd:element"/><xsl:text>&#xa;</xsl:text>
        <xsl:apply-templates select="xsd:annotation"/>
        <xsl:text>&#xa;}</xsl:text>
    </xsl:template>
    

    我编辑了您的 XSL 并在下面的 XSL 文档中进行了这些更改:

    <xsl:stylesheet version="1.0" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>
    
        <xsl:template match="*"/>
    
        <xsl:template match="/">
            <xsl:text>&lt;?php </xsl:text>
            <xsl:apply-templates select="xsd:schema"/>
        </xsl:template>
    
        <xsl:template match="xsd:schema">
            <xsl:text>interface FromXsd {&#xa;</xsl:text>
            <xsl:apply-templates select="xsd:element"/><xsl:text>&#xa;</xsl:text>
            <xsl:apply-templates select="xsd:annotation"/>
            <xsl:text>&#xa;}</xsl:text>
        </xsl:template>
    
        <xsl:template match="xsd:element">
            <xsl:apply-templates select="xsd:annotation"/>
            <xsl:text>    abstract public function build</xsl:text>
            <xsl:value-of select="normalize-space(@name)"/>
            <xsl:text>XmlString(</xsl:text>
            <xsl:value-of select="@type"/><xsl:text> $a</xsl:text>
            <xsl:text>);</xsl:text>
        </xsl:template>
    
        <xsl:template match="xsd:annotation">
            <xsl:text>    /* </xsl:text>
            <xsl:value-of select="normalize-space(.)"/>
            <xsl:text> */</xsl:text>
        </xsl:template>
    
    </xsl:stylesheet>
    

    如果您有如下输入:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="Foo" type="Bar"/>
        <xsd:simpleType name="Bar">
            <xsd:restriction base="xsd:string">
                <xsd:maxLength value="32"/>
            </xsd:restriction>
        </xsd:simpleType>
        <xsd:annotation>
            <xsd:documentation>This is a comment</xsd:documentation>
        </xsd:annotation>
    </xsd:schema>
    

    它将产生以下结果:

    <?php interface FromXsd {
        abstract public function buildFooXmlString(Bar $a);
        /* This is a comment */
    }
    

    【讨论】:

    • 优秀。我陷入了我需要从element 节点重复到*Type 元素的想法。谢谢你让我失望。
    • @VigneshKumar 这是这个问题的链接,这似乎不是你的问题。您需要什么帮助?
    猜你喜欢
    • 1970-01-01
    • 2013-04-21
    • 2018-12-01
    • 2011-04-22
    • 1970-01-01
    • 2020-03-18
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多