php - 将元素与动态属性值相匹配

标签 php xml xslt xpath xsd

我正在尝试构建一个转换原型(prototype),将 xsl:schema 转换为 PHP 界面。我在匹配 xsd:simpleType 元素时遇到了一些麻烦,这些元素的 name 属性与 xsd:element< 的 type 属性相匹配 元素。假设我有这样的架构:

<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 属性与 elementtype 匹配的 simpleType 节点? (xsd 类型的名称必须是唯一的。)

最佳答案

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

如果您想允许处理节点的所有子节点,则应包含一个空 <xsl:apply-templates/>里面xsd:schema模板。

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

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

由于您要生成文本,因此应该使用 <xsl:text>控制空白如何分布的元素。例如,如果您使用:

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

您无需担心总是放置 &lt;?php紧接着<xsl:template>之后的文本并且可以正常缩进你的代码。您还可以使用 &#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 */
}

关于php - 将元素与动态属性值相匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23189178/

相关文章:

javascript - Mysql 根据另一个下拉选项填充下拉列表

php - 通过 php/shell 脚本在 linux 中创建一个文件?

文件后面的 Android 布局引用 xml 元素

android - 在Android Studio中制作 "glowing"矢量图像

xml - 使用 XSLT 转换子节点但保留其余部分不变

xslt - 如何使用 XSLT 用它们的转义变体替换某些字符?

xml - Xpath 选择节点直到标记

php - 通过php导入sql

php - mysql 列用于插入和不同的列用于更新

java - 如何使用 JAXB 将复杂的 XML 元素映射到 Java 类属性