在变量中添加额外的字符串 - PHP

时间:2016-11-15 18:00:31

标签: php xml xpath concat

这是我的问题。我想创建一个函数,它接受一个包含xpath的外部变量,一旦函数运行,我想添加到同一个变量来创建一个计数器。

所以我有外部变量:

<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=S192-169-136-24\ABPATH;Initial Catalog=aspnet-cs1-20160511031253;Integrated Security=True" providerName="System.Data.SqlClient" />
<add name="CS1" connectionString="Data Source=S192-169-136-24\ABPATH;Initial Catalog=CS1;Integrated Security=True" providerName="System.Data.SqlClient" />
 </connectionStrings>
 <system.web>
 <authentication mode="None" />
 <compilation targetFramework="4.5.2" />
 <httpRuntime maxRequestLength="2097151" targetFramework="4.5.2" requestValidationMode="2.0" requestPathInvalidCharacters="" />
  <pages validateRequest="false">
  <namespaces>
    <add namespace="System.Web.Optimization" />
    <add namespace="Microsoft.AspNet.Identity" />
  </namespaces>
  <controls>
    <add assembly="Microsoft.AspNet.Web.Optimization.WebForms" namespace="Microsoft.AspNet.Web.Optimization.WebForms" tagPrefix="webopt" />
  </controls>
</pages>
<membership>
  <providers>
    <!--
      ASP.NET Membership is disabled in this template. Please visit the following link http://go.microsoft.com/fwlink/?LinkId=301889 to learn about the ASP.NET Membership support in this template
    -->
    <clear />
  </providers>
</membership>
<profile>
  <providers>
    <!--
      ASP.NET Membership Profile is disabled in this template. Please visit the following link http://go.microsoft.com/fwlink/?LinkId=301889 to learn about the ASP.NET Membership support in this template
    -->
    <clear />
  </providers>
</profile>
<roleManager defaultProvider="DefaultConnection" enabled="true">
<providers>
   <add name="DefaultConnection" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=NUMBER" connectionStringName="DefaultConnection" applicationName="/" />
 </providers>
</roleManager>
<!--
        If you are deploying to a cloud environment that has multiple web server instances,
        you should change session state mode from "InProc" to "Custom". In addition,
        change the connection string named "DefaultConnection" to connect to an instance
        of SQL Server (including SQL Azure and SQL  Compact) instead of to SQL Server Express.
  -->
  <sessionState mode="InProc" customProvider="DefaultSessionProvider">
  <providers>
    <add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
  </providers>
 </sessionState>
  <httpModules>
  <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
 </httpModules>
 </system.web>
 <system.webServer>
 <rewrite>
    <rules>
    <rule name="HTTP to HTTPS redirect" stopProcessing="true"> 
    <match url="(.*)" /> 
    <conditions> 
        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
    </conditions> 
    <action type="Redirect" redirectType="Permanent" url="https://{HTTP_HOST}/{R:1}" />
  </rule>   
    </rules>
  </rewrite>
  <modules>
  <remove name="FormsAuthentication" />
  <remove name="ApplicationInsightsWebTracking" />
  <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
</modules>
<validation validateIntegratedModeConfiguration="false" />
    <httpRedirect enabled="false" destination="https://www.pathcertlink.com/" exactDestination="true" />
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  <dependentAssembly>
    <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
    <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="WebGrease" culture="neutral" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" />
    <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Owin" culture="neutral" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Owin.Security.OAuth" culture="neutral" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Owin.Security.Cookies" culture="neutral" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
    </dependentAssembly>
    <dependentAssembly>
    <assemblyIdentity name="Microsoft.Owin.Security" culture="neutral" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
    </dependentAssembly>
    </assemblyBinding>
   </runtime>
 <entityFramework>
  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
   <providers>
  <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
   </providers>
  </entityFramework>
  <system.codedom>
 <compilers>
  <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
  <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
  </compilers>
 </system.codedom>
 </configuration>

然后该函数使用一个参数来获取外部变量( $node = $xmlDoc->xpath('//a:Order'); )。像这样:

$node

现在我想在$ node中添加一个计数器,以便它通过“Order”的所有子节点。在函数之外,我会使用:

function loopXML($node) {
    i=1; //counter variable
}

但是在函数内部,我不知道如何连接它。有谁知道我怎么能这样做?

编辑: 此外,应该注意我已经创建了一个任意命名空间:

$child = $xmlDoc->xpath('//a:Order['.$i.']/*'); 

2 个答案:

答案 0 :(得分:1)

SimpleXMLElement::xpath()使用与SimpleXML元素关联的节点作为上下文,因此您可以执行以下操作:

foreach ($xmlDoc->xpath('//a:Order') as $order) {
  foreach ($order->xpath('*') as $field) {
    ...
  }
} 

但SimpleXMLElement :: children()是元素子节点的列表,因此它返回与Xpath表达式*相同或更准确的'*[namespace-uri == ""]'。第一个参数是您要获取的子项的名称空间。

foreach ($xmlDoc->xpath('//a:Order') as $order) {
  foreach ($order->children() as $field) {
    ...
  }
}

这可以很容易地重构为函数。

function getRecord(SimpleXMLelement $order, $namespace) {
  $result = [];
  foreach ($order->children($namespace) as $field) {
    $result[$field->getName()] = (string)$field;
  }
  return $result;
}

您应该始终依赖于实际的命名空间,而不是前缀。前缀可以更改并且是可选的。

全部放在一起:

$xml = <<<'XML'
<a:orders xmlns:a="urn:a">
  <a:order>
    <a:foo>bar</a:foo>
    <a:answer>42</a:answer>
  </a:order>
</a:orders>
XML;

$namespace = 'urn:a';

$orders = new SimpleXMLElement($xml);
$orders->registerXpathNamespace('a', $namespace);

function getRecord(SimpleXMLelement $order, $namespace = NULL) {
  $result = [];
  foreach ($order->children($namespace) as $field) {
    $result[$field->getName()] = (string)$field;
  }
  return $result;
} 

foreach ($orders->xpath('//a:order') as $order) {
  var_dump(getRecord($order, $namespace));
}

输出:

array(2) {
  ["foo"]=>
  string(3) "bar"
  ["answer"]=>
  string(2) "42"
}

答案 1 :(得分:0)

所以我用很多谷歌搜索和ThW的帮助解决了这个问题。所以对所有有帮助的人,谢谢。以下是我如何使用它:

 $orderPNode = '//a:Order'; 
 $amazonRawXML = 'AmazonRaw.xml';
 $amazonRawCSV = 'AmazonRaw.csv';


function loopXML($xmlDoc, $node, $writeCsv) {
$i = 1;
$xmlDocs = simplexml_load_file($xmlDoc);
$result = [];

foreach($xmlDocs->getDocNamespaces() as $strPrefix => $strNamespace) {
    if(strlen($strPrefix)==0) {
        $strPrefix="a"; //Assign an arbitrary namespace prefix.
    }
$xmlDocs->registerXPathNamespace($strPrefix,$strNamespace);
}

file_put_contents($writeCsv, ""); // Clear contents of csv file after each go

$nodeP = $xmlDocs->xpath($node); 

foreach ($nodeP as $n) {
    $nodeC = $xmlDocs->xpath($node.'['.$i.']/*');
    if($nodeC) {
        foreach ($nodeC as $value) {
            $values[] = $value;
        }
    $write = fopen($writeCsv, 'a'); 
    fputcsv($write, $values);
    fclose($write);

    $values = [];
    $i++;
    } else {
        $result[] = $n;
        $i++;
    }

}
return $result;
}
loopXML($amazonRawXML, $orderPNode, $amazonRawCSV);